{-# LANGUAGE CPP #-}
module Database.Beam.Migrate.Types.Predicates where
import Database.Beam
import Database.Beam.Backend.SQL.SQL92 (IsSql92TableNameSyntax(..))
import Database.Beam.Schema.Tables
import Control.DeepSeq
import Data.Aeson
import Data.Text (Text)
import Data.Hashable
import Data.Typeable
#if !MIN_VERSION_base(4, 11, 0)
import Data.Semigroup
#endif
import Lens.Micro ((^.))
class (Typeable p, Hashable p, Eq p) => DatabasePredicate p where
englishDescription :: p -> String
predicateSpecificity :: proxy p -> PredicateSpecificity
serializePredicate :: p -> Value
predicateCascadesDropOn :: DatabasePredicate p' => p -> p' -> Bool
predicateCascadesDropOn _ _ = False
data SomeDatabasePredicate where
SomeDatabasePredicate :: DatabasePredicate p
=> p -> SomeDatabasePredicate
instance NFData SomeDatabasePredicate where
rnf p' = p' `seq` ()
instance Show SomeDatabasePredicate where
showsPrec _ (SomeDatabasePredicate p') =
('(':) . shows (typeOf p') . (": " ++) . (englishDescription p' ++) . (')':)
instance Eq SomeDatabasePredicate where
SomeDatabasePredicate a == SomeDatabasePredicate b =
case cast a of
Nothing -> False
Just a' -> a' == b
instance Hashable SomeDatabasePredicate where
hashWithSalt salt (SomeDatabasePredicate p') = hashWithSalt salt (typeOf p', p')
data PredicateSpecificity
= PredicateSpecificityOnlyBackend String
| PredicateSpecificityAllBackends
deriving (Show, Eq, Generic)
instance Hashable PredicateSpecificity
instance ToJSON PredicateSpecificity where
toJSON PredicateSpecificityAllBackends = "all"
toJSON (PredicateSpecificityOnlyBackend s) = object [ "backend" .= toJSON s ]
instance FromJSON PredicateSpecificity where
parseJSON "all" = pure PredicateSpecificityAllBackends
parseJSON (Object o) = PredicateSpecificityOnlyBackend <$> o .: "backend"
parseJSON _ = fail "PredicateSource"
p :: DatabasePredicate p => p -> SomeDatabasePredicate
p = SomeDatabasePredicate
data QualifiedName = QualifiedName (Maybe Text) Text
deriving (Show, Eq, Ord)
instance ToJSON QualifiedName where
toJSON (QualifiedName Nothing t) = toJSON t
toJSON (QualifiedName (Just s) t) = object [ "schema" .= s, "name" .= t ]
instance FromJSON QualifiedName where
parseJSON s@(String {}) = QualifiedName Nothing <$> parseJSON s
parseJSON (Object o) = QualifiedName <$> o .: "schema" <*> o .: "name"
parseJSON _ = fail "QualifiedName: expects either string or {schema: ..., name: ...}"
instance Hashable QualifiedName where
hashWithSalt s (QualifiedName sch t) =
hashWithSalt s (sch, t)
qname :: IsDatabaseEntity be entity => DatabaseEntityDescriptor be entity -> QualifiedName
qname e = QualifiedName (e ^. dbEntitySchema) (e ^. dbEntityName)
qnameAsText :: QualifiedName -> Text
qnameAsText (QualifiedName Nothing tbl) = tbl
qnameAsText (QualifiedName (Just sch) tbl) = sch <> "." <> tbl
qnameAsTableName :: IsSql92TableNameSyntax syntax => QualifiedName -> syntax
qnameAsTableName (QualifiedName sch t) = tableName sch t
newtype TableCheck = TableCheck (forall tbl. Table tbl => QualifiedName -> tbl (TableField tbl) -> SomeDatabasePredicate)
newtype DomainCheck = DomainCheck (QualifiedName -> SomeDatabasePredicate)
newtype FieldCheck = FieldCheck (QualifiedName -> Text -> SomeDatabasePredicate)