{-# LANGUAGE DeriveAnyClass #-}
{-# LANGUAGE DeriveGeneric  #-}

module PostgREST.DbStructure.Identifiers
  ( QualifiedIdentifier(..)
  , Schema
  , TableName
  , FieldName
  , toQi
  ) where

import qualified Data.Aeson as JSON
import qualified Data.Text  as T
import qualified GHC.Show

import Protolude


-- | Represents a pg identifier with a prepended schema name "schema.table".
-- When qiSchema is "", the schema is defined by the pg search_path.
data QualifiedIdentifier = QualifiedIdentifier
  { QualifiedIdentifier -> Schema
qiSchema :: Schema
  , QualifiedIdentifier -> Schema
qiName   :: TableName
  }
  deriving (QualifiedIdentifier -> QualifiedIdentifier -> Bool
(QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> (QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> Eq QualifiedIdentifier
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c/= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
== :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c== :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
Eq, Eq QualifiedIdentifier
Eq QualifiedIdentifier
-> (QualifiedIdentifier -> QualifiedIdentifier -> Ordering)
-> (QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> (QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> (QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> (QualifiedIdentifier -> QualifiedIdentifier -> Bool)
-> (QualifiedIdentifier
    -> QualifiedIdentifier -> QualifiedIdentifier)
-> (QualifiedIdentifier
    -> QualifiedIdentifier -> QualifiedIdentifier)
-> Ord QualifiedIdentifier
QualifiedIdentifier -> QualifiedIdentifier -> Bool
QualifiedIdentifier -> QualifiedIdentifier -> Ordering
QualifiedIdentifier -> QualifiedIdentifier -> QualifiedIdentifier
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
min :: QualifiedIdentifier -> QualifiedIdentifier -> QualifiedIdentifier
$cmin :: QualifiedIdentifier -> QualifiedIdentifier -> QualifiedIdentifier
max :: QualifiedIdentifier -> QualifiedIdentifier -> QualifiedIdentifier
$cmax :: QualifiedIdentifier -> QualifiedIdentifier -> QualifiedIdentifier
>= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c>= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
> :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c> :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
<= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c<= :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
< :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
$c< :: QualifiedIdentifier -> QualifiedIdentifier -> Bool
compare :: QualifiedIdentifier -> QualifiedIdentifier -> Ordering
$ccompare :: QualifiedIdentifier -> QualifiedIdentifier -> Ordering
$cp1Ord :: Eq QualifiedIdentifier
Ord, (forall x. QualifiedIdentifier -> Rep QualifiedIdentifier x)
-> (forall x. Rep QualifiedIdentifier x -> QualifiedIdentifier)
-> Generic QualifiedIdentifier
forall x. Rep QualifiedIdentifier x -> QualifiedIdentifier
forall x. QualifiedIdentifier -> Rep QualifiedIdentifier x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cto :: forall x. Rep QualifiedIdentifier x -> QualifiedIdentifier
$cfrom :: forall x. QualifiedIdentifier -> Rep QualifiedIdentifier x
Generic, [QualifiedIdentifier] -> Encoding
[QualifiedIdentifier] -> Value
QualifiedIdentifier -> Encoding
QualifiedIdentifier -> Value
(QualifiedIdentifier -> Value)
-> (QualifiedIdentifier -> Encoding)
-> ([QualifiedIdentifier] -> Value)
-> ([QualifiedIdentifier] -> Encoding)
-> ToJSON QualifiedIdentifier
forall a.
(a -> Value)
-> (a -> Encoding)
-> ([a] -> Value)
-> ([a] -> Encoding)
-> ToJSON a
toEncodingList :: [QualifiedIdentifier] -> Encoding
$ctoEncodingList :: [QualifiedIdentifier] -> Encoding
toJSONList :: [QualifiedIdentifier] -> Value
$ctoJSONList :: [QualifiedIdentifier] -> Value
toEncoding :: QualifiedIdentifier -> Encoding
$ctoEncoding :: QualifiedIdentifier -> Encoding
toJSON :: QualifiedIdentifier -> Value
$ctoJSON :: QualifiedIdentifier -> Value
JSON.ToJSON, ToJSONKeyFunction [QualifiedIdentifier]
ToJSONKeyFunction QualifiedIdentifier
ToJSONKeyFunction QualifiedIdentifier
-> ToJSONKeyFunction [QualifiedIdentifier]
-> ToJSONKey QualifiedIdentifier
forall a.
ToJSONKeyFunction a -> ToJSONKeyFunction [a] -> ToJSONKey a
toJSONKeyList :: ToJSONKeyFunction [QualifiedIdentifier]
$ctoJSONKeyList :: ToJSONKeyFunction [QualifiedIdentifier]
toJSONKey :: ToJSONKeyFunction QualifiedIdentifier
$ctoJSONKey :: ToJSONKeyFunction QualifiedIdentifier
JSON.ToJSONKey)

instance Hashable QualifiedIdentifier

instance Show QualifiedIdentifier where
  show :: QualifiedIdentifier -> String
show (QualifiedIdentifier Schema
s Schema
i) =
    (if Schema -> Bool
T.null Schema
s then String
forall a. Monoid a => a
mempty else Schema -> String
forall a b. ConvertText a b => a -> b
toS Schema
s String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
".") String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Schema -> String
forall a b. ConvertText a b => a -> b
toS Schema
i

-- TODO: Handle a case where the QI comes like this: "my.fav.schema"."my.identifier"
-- Right now it only handles the schema.identifier case
toQi :: Text -> QualifiedIdentifier
toQi :: Schema -> QualifiedIdentifier
toQi Schema
txt = case Int -> Schema -> Schema
T.drop Int
1 (Schema -> Schema) -> (Schema, Schema) -> (Schema, Schema)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Schema -> Schema -> (Schema, Schema)
T.breakOn Schema
"." Schema
txt of
  (Schema
i, Schema
"") -> Schema -> Schema -> QualifiedIdentifier
QualifiedIdentifier Schema
forall a. Monoid a => a
mempty Schema
i
  (Schema
s, Schema
i)  -> Schema -> Schema -> QualifiedIdentifier
QualifiedIdentifier Schema
s Schema
i

type Schema = Text
type TableName = Text
type FieldName = Text