module Hasura.RQL.DDL.Schema.Diff
  ( TableMeta (..),
    FunctionMeta (..),
    TablesDiff (..),
    FunctionsDiff (..),
    ComputedFieldMeta (..),
    getTablesDiff,
    processTablesDiff,
    getIndirectDependenciesFromTableDiff,
    getFunctionsDiff,
    getOverloadedFunctions,
  )
where

import Control.Lens ((.~))
import Data.Aeson
import Data.HashMap.Strict qualified as HashMap
import Data.HashMap.Strict.InsOrd qualified as InsOrdHashMap
import Data.HashSet qualified as HS
import Data.List.Extended
import Data.List.NonEmpty qualified as NE
import Data.Text.Extended
import Hasura.Backends.Postgres.SQL.Types hiding (ConstraintName, FunctionName, TableName)
import Hasura.Base.Error
import Hasura.Function.Cache
import Hasura.Prelude
import Hasura.RQL.DDL.Schema.Rename
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.ComputedField
import Hasura.RQL.Types.Metadata
import Hasura.RQL.Types.Metadata.Backend
import Hasura.RQL.Types.SchemaCache
import Hasura.RQL.Types.SchemaCacheTypes
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Table.API
import Hasura.Table.Cache
import Hasura.Table.Metadata (tmConfiguration)
import Language.GraphQL.Draft.Syntax qualified as G

data FunctionMeta b = FunctionMeta
  { forall (b :: BackendType). FunctionMeta b -> OID
fmOid :: OID,
    forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction :: FunctionName b,
    forall (b :: BackendType). FunctionMeta b -> FunctionVolatility
fmType :: FunctionVolatility
  }
  deriving ((forall x. FunctionMeta b -> Rep (FunctionMeta b) x)
-> (forall x. Rep (FunctionMeta b) x -> FunctionMeta b)
-> Generic (FunctionMeta b)
forall x. Rep (FunctionMeta b) x -> FunctionMeta b
forall x. FunctionMeta b -> Rep (FunctionMeta b) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) x.
Rep (FunctionMeta b) x -> FunctionMeta b
forall (b :: BackendType) x.
FunctionMeta b -> Rep (FunctionMeta b) x
$cfrom :: forall (b :: BackendType) x.
FunctionMeta b -> Rep (FunctionMeta b) x
from :: forall x. FunctionMeta b -> Rep (FunctionMeta b) x
$cto :: forall (b :: BackendType) x.
Rep (FunctionMeta b) x -> FunctionMeta b
to :: forall x. Rep (FunctionMeta b) x -> FunctionMeta b
Generic)

deriving instance (Backend b) => Show (FunctionMeta b)

deriving instance (Backend b) => Eq (FunctionMeta b)

instance (Backend b) => FromJSON (FunctionMeta b) where
  parseJSON :: Value -> Parser (FunctionMeta b)
parseJSON = Options -> Value -> Parser (FunctionMeta b)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
hasuraJSON

instance (Backend b) => ToJSON (FunctionMeta b) where
  toJSON :: FunctionMeta b -> Value
toJSON = Options -> FunctionMeta b -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
hasuraJSON

data ComputedFieldMeta b = ComputedFieldMeta
  { forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName :: ComputedFieldName,
    forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta :: FunctionMeta b
  }
  deriving ((forall x. ComputedFieldMeta b -> Rep (ComputedFieldMeta b) x)
-> (forall x. Rep (ComputedFieldMeta b) x -> ComputedFieldMeta b)
-> Generic (ComputedFieldMeta b)
forall x. Rep (ComputedFieldMeta b) x -> ComputedFieldMeta b
forall x. ComputedFieldMeta b -> Rep (ComputedFieldMeta b) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall (b :: BackendType) x.
Rep (ComputedFieldMeta b) x -> ComputedFieldMeta b
forall (b :: BackendType) x.
ComputedFieldMeta b -> Rep (ComputedFieldMeta b) x
$cfrom :: forall (b :: BackendType) x.
ComputedFieldMeta b -> Rep (ComputedFieldMeta b) x
from :: forall x. ComputedFieldMeta b -> Rep (ComputedFieldMeta b) x
$cto :: forall (b :: BackendType) x.
Rep (ComputedFieldMeta b) x -> ComputedFieldMeta b
to :: forall x. Rep (ComputedFieldMeta b) x -> ComputedFieldMeta b
Generic, Int -> ComputedFieldMeta b -> ShowS
[ComputedFieldMeta b] -> ShowS
ComputedFieldMeta b -> String
(Int -> ComputedFieldMeta b -> ShowS)
-> (ComputedFieldMeta b -> String)
-> ([ComputedFieldMeta b] -> ShowS)
-> Show (ComputedFieldMeta b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (b :: BackendType).
Backend b =>
Int -> ComputedFieldMeta b -> ShowS
forall (b :: BackendType).
Backend b =>
[ComputedFieldMeta b] -> ShowS
forall (b :: BackendType).
Backend b =>
ComputedFieldMeta b -> String
$cshowsPrec :: forall (b :: BackendType).
Backend b =>
Int -> ComputedFieldMeta b -> ShowS
showsPrec :: Int -> ComputedFieldMeta b -> ShowS
$cshow :: forall (b :: BackendType).
Backend b =>
ComputedFieldMeta b -> String
show :: ComputedFieldMeta b -> String
$cshowList :: forall (b :: BackendType).
Backend b =>
[ComputedFieldMeta b] -> ShowS
showList :: [ComputedFieldMeta b] -> ShowS
Show, ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
(ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
-> (ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
-> Eq (ComputedFieldMeta b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (b :: BackendType).
Backend b =>
ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
$c== :: forall (b :: BackendType).
Backend b =>
ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
== :: ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
$c/= :: forall (b :: BackendType).
Backend b =>
ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
/= :: ComputedFieldMeta b -> ComputedFieldMeta b -> Bool
Eq)

instance (Backend b) => FromJSON (ComputedFieldMeta b) where
  parseJSON :: Value -> Parser (ComputedFieldMeta b)
parseJSON = Options -> Value -> Parser (ComputedFieldMeta b)
forall a.
(Generic a, GFromJSON Zero (Rep a)) =>
Options -> Value -> Parser a
genericParseJSON Options
hasuraJSON {omitNothingFields :: Bool
omitNothingFields = Bool
True}

instance (Backend b) => ToJSON (ComputedFieldMeta b) where
  toJSON :: ComputedFieldMeta b -> Value
toJSON = Options -> ComputedFieldMeta b -> Value
forall a.
(Generic a, GToJSON' Value Zero (Rep a)) =>
Options -> a -> Value
genericToJSON Options
hasuraJSON {omitNothingFields :: Bool
omitNothingFields = Bool
True}

data TableMeta (b :: BackendType) = TableMeta
  { forall (b :: BackendType). TableMeta b -> TableName b
tmTable :: TableName b,
    forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo :: DBTableMetadata b,
    forall (b :: BackendType). TableMeta b -> [ComputedFieldMeta b]
tmComputedFields :: [ComputedFieldMeta b]
  }
  deriving (Int -> TableMeta b -> ShowS
[TableMeta b] -> ShowS
TableMeta b -> String
(Int -> TableMeta b -> ShowS)
-> (TableMeta b -> String)
-> ([TableMeta b] -> ShowS)
-> Show (TableMeta b)
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
forall (b :: BackendType). Backend b => Int -> TableMeta b -> ShowS
forall (b :: BackendType). Backend b => [TableMeta b] -> ShowS
forall (b :: BackendType). Backend b => TableMeta b -> String
$cshowsPrec :: forall (b :: BackendType). Backend b => Int -> TableMeta b -> ShowS
showsPrec :: Int -> TableMeta b -> ShowS
$cshow :: forall (b :: BackendType). Backend b => TableMeta b -> String
show :: TableMeta b -> String
$cshowList :: forall (b :: BackendType). Backend b => [TableMeta b] -> ShowS
showList :: [TableMeta b] -> ShowS
Show, TableMeta b -> TableMeta b -> Bool
(TableMeta b -> TableMeta b -> Bool)
-> (TableMeta b -> TableMeta b -> Bool) -> Eq (TableMeta b)
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
forall (b :: BackendType).
Backend b =>
TableMeta b -> TableMeta b -> Bool
$c== :: forall (b :: BackendType).
Backend b =>
TableMeta b -> TableMeta b -> Bool
== :: TableMeta b -> TableMeta b -> Bool
$c/= :: forall (b :: BackendType).
Backend b =>
TableMeta b -> TableMeta b -> Bool
/= :: TableMeta b -> TableMeta b -> Bool
Eq)

data ComputedFieldDiff (b :: BackendType) = ComputedFieldDiff
  { forall (b :: BackendType).
ComputedFieldDiff b -> [ComputedFieldName]
_cfdDropped :: [ComputedFieldName],
    forall (b :: BackendType).
ComputedFieldDiff b -> [(ComputedFieldMeta b, ComputedFieldMeta b)]
_cfdAltered :: [(ComputedFieldMeta b, ComputedFieldMeta b)],
    forall (b :: BackendType).
ComputedFieldDiff b -> [(ComputedFieldName, FunctionName b)]
_cfdOverloaded :: [(ComputedFieldName, FunctionName b)]
  }

deriving instance (Backend b) => Show (ComputedFieldDiff b)

deriving instance (Backend b) => Eq (ComputedFieldDiff b)

data TableDiff (b :: BackendType) = TableDiff
  { forall (b :: BackendType). TableDiff b -> Maybe (TableName b)
_tdNewName :: Maybe (TableName b),
    forall (b :: BackendType). TableDiff b -> [Column b]
_tdDroppedCols :: [Column b],
    forall (b :: BackendType).
TableDiff b -> [(RawColumnInfo b, RawColumnInfo b)]
_tdAlteredCols :: [(RawColumnInfo b, RawColumnInfo b)],
    forall (b :: BackendType). TableDiff b -> [ConstraintName b]
_tdDroppedFKeyCons :: [ConstraintName b],
    forall (b :: BackendType). TableDiff b -> ComputedFieldDiff b
_tdComputedFields :: ComputedFieldDiff b,
    -- The final list of uniq/primary constraint names
    -- used for generating types on_conflict clauses
    -- TODO: this ideally should't be part of TableDiff
    forall (b :: BackendType). TableDiff b -> [ConstraintName b]
_tdUniqOrPriCons :: [ConstraintName b],
    forall (b :: BackendType). TableDiff b -> Maybe PGDescription
_tdNewDescription :: Maybe PGDescription
  }

getTableDiff ::
  (Backend b) =>
  TableMeta b ->
  TableMeta b ->
  TableDiff b
getTableDiff :: forall (b :: BackendType).
Backend b =>
TableMeta b -> TableMeta b -> TableDiff b
getTableDiff TableMeta b
oldtm TableMeta b
newtm =
  Maybe (TableName b)
-> [Column b]
-> [(RawColumnInfo b, RawColumnInfo b)]
-> [ConstraintName b]
-> ComputedFieldDiff b
-> [ConstraintName b]
-> Maybe PGDescription
-> TableDiff b
forall (b :: BackendType).
Maybe (TableName b)
-> [Column b]
-> [(RawColumnInfo b, RawColumnInfo b)]
-> [ConstraintName b]
-> ComputedFieldDiff b
-> [ConstraintName b]
-> Maybe PGDescription
-> TableDiff b
TableDiff
    Maybe (TableName b)
mNewName
    [Column b]
droppedCols
    [(RawColumnInfo b, RawColumnInfo b)]
alteredCols
    [ConstraintName b]
droppedFKeyConstraints
    ComputedFieldDiff b
computedFieldDiff
    [ConstraintName b]
uniqueOrPrimaryCons
    Maybe PGDescription
mNewDesc
  where
    mNewName :: Maybe (TableName b)
mNewName = Maybe (TableName b)
-> Maybe (TableName b) -> Bool -> Maybe (TableName b)
forall a. a -> a -> Bool -> a
bool (TableName b -> Maybe (TableName b)
forall a. a -> Maybe a
Just (TableName b -> Maybe (TableName b))
-> TableName b -> Maybe (TableName b)
forall a b. (a -> b) -> a -> b
$ TableMeta b -> TableName b
forall (b :: BackendType). TableMeta b -> TableName b
tmTable TableMeta b
newtm) Maybe (TableName b)
forall a. Maybe a
Nothing (Bool -> Maybe (TableName b)) -> Bool -> Maybe (TableName b)
forall a b. (a -> b) -> a -> b
$ TableMeta b -> TableName b
forall (b :: BackendType). TableMeta b -> TableName b
tmTable TableMeta b
oldtm TableName b -> TableName b -> Bool
forall a. Eq a => a -> a -> Bool
== TableMeta b -> TableName b
forall (b :: BackendType). TableMeta b -> TableName b
tmTable TableMeta b
newtm
    oldCols :: [RawColumnInfo b]
oldCols = DBTableMetadata b -> [RawColumnInfo b]
forall (b :: BackendType). DBTableMetadata b -> [RawColumnInfo b]
_ptmiColumns (DBTableMetadata b -> [RawColumnInfo b])
-> DBTableMetadata b -> [RawColumnInfo b]
forall a b. (a -> b) -> a -> b
$ TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo TableMeta b
oldtm
    newCols :: [RawColumnInfo b]
newCols = DBTableMetadata b -> [RawColumnInfo b]
forall (b :: BackendType). DBTableMetadata b -> [RawColumnInfo b]
_ptmiColumns (DBTableMetadata b -> [RawColumnInfo b])
-> DBTableMetadata b -> [RawColumnInfo b]
forall a b. (a -> b) -> a -> b
$ TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo TableMeta b
newtm

    uniqueOrPrimaryCons :: [ConstraintName b]
uniqueOrPrimaryCons =
      (Constraint b -> ConstraintName b)
-> [Constraint b] -> [ConstraintName b]
forall a b. (a -> b) -> [a] -> [b]
map Constraint b -> ConstraintName b
forall (b :: BackendType). Constraint b -> ConstraintName b
_cName
        ([Constraint b] -> [ConstraintName b])
-> [Constraint b] -> [ConstraintName b]
forall a b. (a -> b) -> a -> b
$ Maybe (Constraint b) -> [Constraint b]
forall a. Maybe a -> [a]
maybeToList (PrimaryKey b (Column b) -> Constraint b
forall (b :: BackendType) a. PrimaryKey b a -> Constraint b
_pkConstraint (PrimaryKey b (Column b) -> Constraint b)
-> Maybe (PrimaryKey b (Column b)) -> Maybe (Constraint b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> DBTableMetadata b -> Maybe (PrimaryKey b (Column b))
forall (b :: BackendType).
DBTableMetadata b -> Maybe (PrimaryKey b (Column b))
_ptmiPrimaryKey (TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo TableMeta b
newtm))
        [Constraint b] -> [Constraint b] -> [Constraint b]
forall a. Semigroup a => a -> a -> a
<> (UniqueConstraint b -> Constraint b
forall (b :: BackendType). UniqueConstraint b -> Constraint b
_ucConstraint (UniqueConstraint b -> Constraint b)
-> [UniqueConstraint b] -> [Constraint b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashSet (UniqueConstraint b) -> [UniqueConstraint b]
forall a. HashSet a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (DBTableMetadata b -> HashSet (UniqueConstraint b)
forall (b :: BackendType).
DBTableMetadata b -> HashSet (UniqueConstraint b)
_ptmiUniqueConstraints (TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo TableMeta b
newtm)))

    mNewDesc :: Maybe PGDescription
mNewDesc = DBTableMetadata b -> Maybe PGDescription
forall (b :: BackendType). DBTableMetadata b -> Maybe PGDescription
_ptmiDescription (DBTableMetadata b -> Maybe PGDescription)
-> DBTableMetadata b -> Maybe PGDescription
forall a b. (a -> b) -> a -> b
$ TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo TableMeta b
newtm

    droppedCols :: [Column b]
droppedCols = (RawColumnInfo b -> Column b) -> [RawColumnInfo b] -> [Column b]
forall a b. (a -> b) -> [a] -> [b]
map RawColumnInfo b -> Column b
forall (b :: BackendType). RawColumnInfo b -> Column b
rciName ([RawColumnInfo b] -> [Column b])
-> [RawColumnInfo b] -> [Column b]
forall a b. (a -> b) -> a -> b
$ (RawColumnInfo b -> Int)
-> [RawColumnInfo b] -> [RawColumnInfo b] -> [RawColumnInfo b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn RawColumnInfo b -> Int
forall (b :: BackendType). RawColumnInfo b -> Int
rciPosition [RawColumnInfo b]
oldCols [RawColumnInfo b]
newCols
    existingCols :: [(RawColumnInfo b, RawColumnInfo b)]
existingCols = (RawColumnInfo b -> Int)
-> [RawColumnInfo b]
-> [RawColumnInfo b]
-> [(RawColumnInfo b, RawColumnInfo b)]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [(v, v)]
getOverlapWith RawColumnInfo b -> Int
forall (b :: BackendType). RawColumnInfo b -> Int
rciPosition [RawColumnInfo b]
oldCols [RawColumnInfo b]
newCols
    alteredCols :: [(RawColumnInfo b, RawColumnInfo b)]
alteredCols = ((RawColumnInfo b, RawColumnInfo b) -> Bool)
-> [(RawColumnInfo b, RawColumnInfo b)]
-> [(RawColumnInfo b, RawColumnInfo b)]
forall a. (a -> Bool) -> [a] -> [a]
filter ((RawColumnInfo b -> RawColumnInfo b -> Bool)
-> (RawColumnInfo b, RawColumnInfo b) -> Bool
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry RawColumnInfo b -> RawColumnInfo b -> Bool
forall a. Eq a => a -> a -> Bool
(/=)) [(RawColumnInfo b, RawColumnInfo b)]
existingCols

    -- foreign keys are considered dropped only if their oid
    -- and (ref-table, column mapping) are changed
    droppedFKeyConstraints :: [ConstraintName b]
droppedFKeyConstraints =
      (ForeignKey b -> ConstraintName b)
-> [ForeignKey b] -> [ConstraintName b]
forall a b. (a -> b) -> [a] -> [b]
map (Constraint b -> ConstraintName b
forall (b :: BackendType). Constraint b -> ConstraintName b
_cName (Constraint b -> ConstraintName b)
-> (ForeignKey b -> Constraint b)
-> ForeignKey b
-> ConstraintName b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignKey b -> Constraint b
forall (b :: BackendType). ForeignKey b -> Constraint b
_fkConstraint)
        ([ForeignKey b] -> [ConstraintName b])
-> [ForeignKey b] -> [ConstraintName b]
forall a b. (a -> b) -> a -> b
$ HashSet (ForeignKey b) -> [ForeignKey b]
forall a. HashSet a -> [a]
HS.toList
        (HashSet (ForeignKey b) -> [ForeignKey b])
-> HashSet (ForeignKey b) -> [ForeignKey b]
forall a b. (a -> b) -> a -> b
$ HashSet (ForeignKey b)
droppedFKeysWithOid
        HashSet (ForeignKey b)
-> HashSet (ForeignKey b) -> HashSet (ForeignKey b)
forall a. (Eq a, Hashable a) => HashSet a -> HashSet a -> HashSet a
`HS.intersection` HashSet (ForeignKey b)
droppedFKeysWithUniq
    tmForeignKeys :: TableMeta b -> [ForeignKey b]
tmForeignKeys = (ForeignKeyMetadata b -> ForeignKey b)
-> [ForeignKeyMetadata b] -> [ForeignKey b]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ForeignKeyMetadata b -> ForeignKey b
forall (b :: BackendType). ForeignKeyMetadata b -> ForeignKey b
unForeignKeyMetadata ([ForeignKeyMetadata b] -> [ForeignKey b])
-> (TableMeta b -> [ForeignKeyMetadata b])
-> TableMeta b
-> [ForeignKey b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashSet (ForeignKeyMetadata b) -> [ForeignKeyMetadata b]
forall a. HashSet a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (HashSet (ForeignKeyMetadata b) -> [ForeignKeyMetadata b])
-> (TableMeta b -> HashSet (ForeignKeyMetadata b))
-> TableMeta b
-> [ForeignKeyMetadata b]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DBTableMetadata b -> HashSet (ForeignKeyMetadata b)
forall (b :: BackendType).
DBTableMetadata b -> HashSet (ForeignKeyMetadata b)
_ptmiForeignKeys (DBTableMetadata b -> HashSet (ForeignKeyMetadata b))
-> (TableMeta b -> DBTableMetadata b)
-> TableMeta b
-> HashSet (ForeignKeyMetadata b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo
    droppedFKeysWithOid :: HashSet (ForeignKey b)
droppedFKeysWithOid =
      [ForeignKey b] -> HashSet (ForeignKey b)
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList
        ([ForeignKey b] -> HashSet (ForeignKey b))
-> [ForeignKey b] -> HashSet (ForeignKey b)
forall a b. (a -> b) -> a -> b
$ ((ForeignKey b -> OID)
-> [ForeignKey b] -> [ForeignKey b] -> [ForeignKey b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn (Constraint b -> OID
forall (b :: BackendType). Constraint b -> OID
_cOid (Constraint b -> OID)
-> (ForeignKey b -> Constraint b) -> ForeignKey b -> OID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ForeignKey b -> Constraint b
forall (b :: BackendType). ForeignKey b -> Constraint b
_fkConstraint) ([ForeignKey b] -> [ForeignKey b] -> [ForeignKey b])
-> (TableMeta b -> [ForeignKey b])
-> TableMeta b
-> TableMeta b
-> [ForeignKey b]
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` TableMeta b -> [ForeignKey b]
forall {b :: BackendType}. TableMeta b -> [ForeignKey b]
tmForeignKeys) TableMeta b
oldtm TableMeta b
newtm
    droppedFKeysWithUniq :: HashSet (ForeignKey b)
droppedFKeysWithUniq =
      [ForeignKey b] -> HashSet (ForeignKey b)
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList
        ([ForeignKey b] -> HashSet (ForeignKey b))
-> [ForeignKey b] -> HashSet (ForeignKey b)
forall a b. (a -> b) -> a -> b
$ ((ForeignKey b -> (TableName b, NEHashMap (Column b) (Column b)))
-> [ForeignKey b] -> [ForeignKey b] -> [ForeignKey b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn ForeignKey b -> (TableName b, NEHashMap (Column b) (Column b))
forall {b :: BackendType}.
ForeignKey b -> (TableName b, NEHashMap (Column b) (Column b))
mkFKeyUniqId ([ForeignKey b] -> [ForeignKey b] -> [ForeignKey b])
-> (TableMeta b -> [ForeignKey b])
-> TableMeta b
-> TableMeta b
-> [ForeignKey b]
forall b c a. (b -> b -> c) -> (a -> b) -> a -> a -> c
`on` TableMeta b -> [ForeignKey b]
forall {b :: BackendType}. TableMeta b -> [ForeignKey b]
tmForeignKeys) TableMeta b
oldtm TableMeta b
newtm
    mkFKeyUniqId :: ForeignKey b -> (TableName b, NEHashMap (Column b) (Column b))
mkFKeyUniqId (ForeignKey Constraint b
_ TableName b
reftn NEHashMap (Column b) (Column b)
colMap) = (TableName b
reftn, NEHashMap (Column b) (Column b)
colMap)

    -- calculate computed field diff
    oldComputedFieldMeta :: [ComputedFieldMeta b]
oldComputedFieldMeta = TableMeta b -> [ComputedFieldMeta b]
forall (b :: BackendType). TableMeta b -> [ComputedFieldMeta b]
tmComputedFields TableMeta b
oldtm
    newComputedFieldMeta :: [ComputedFieldMeta b]
newComputedFieldMeta = TableMeta b -> [ComputedFieldMeta b]
forall (b :: BackendType). TableMeta b -> [ComputedFieldMeta b]
tmComputedFields TableMeta b
newtm

    droppedComputedFields :: [ComputedFieldName]
droppedComputedFields =
      (ComputedFieldMeta b -> ComputedFieldName)
-> [ComputedFieldMeta b] -> [ComputedFieldName]
forall a b. (a -> b) -> [a] -> [b]
map ComputedFieldMeta b -> ComputedFieldName
forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName
        ([ComputedFieldMeta b] -> [ComputedFieldName])
-> [ComputedFieldMeta b] -> [ComputedFieldName]
forall a b. (a -> b) -> a -> b
$ (ComputedFieldMeta b -> OID)
-> [ComputedFieldMeta b]
-> [ComputedFieldMeta b]
-> [ComputedFieldMeta b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn (FunctionMeta b -> OID
forall (b :: BackendType). FunctionMeta b -> OID
fmOid (FunctionMeta b -> OID)
-> (ComputedFieldMeta b -> FunctionMeta b)
-> ComputedFieldMeta b
-> OID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldMeta b -> FunctionMeta b
forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta) [ComputedFieldMeta b]
oldComputedFieldMeta [ComputedFieldMeta b]
newComputedFieldMeta

    alteredComputedFields :: [(ComputedFieldMeta b, ComputedFieldMeta b)]
alteredComputedFields =
      (ComputedFieldMeta b -> OID)
-> [ComputedFieldMeta b]
-> [ComputedFieldMeta b]
-> [(ComputedFieldMeta b, ComputedFieldMeta b)]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [(v, v)]
getOverlapWith (FunctionMeta b -> OID
forall (b :: BackendType). FunctionMeta b -> OID
fmOid (FunctionMeta b -> OID)
-> (ComputedFieldMeta b -> FunctionMeta b)
-> ComputedFieldMeta b
-> OID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldMeta b -> FunctionMeta b
forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta) [ComputedFieldMeta b]
oldComputedFieldMeta [ComputedFieldMeta b]
newComputedFieldMeta

    overloadedComputedFieldFunctions :: [(ComputedFieldName, FunctionName b)]
overloadedComputedFieldFunctions =
      let getFunction :: ComputedFieldMeta b -> FunctionName b
getFunction = FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction (FunctionMeta b -> FunctionName b)
-> (ComputedFieldMeta b -> FunctionMeta b)
-> ComputedFieldMeta b
-> FunctionName b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldMeta b -> FunctionMeta b
forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta
          getSecondElement :: NonEmpty a -> Maybe a
getSecondElement (a
_ NE.:| [a]
list) = [a] -> Maybe a
forall a. [a] -> Maybe a
listToMaybe [a]
list
       in (NonEmpty (ComputedFieldMeta b)
 -> Maybe (ComputedFieldName, FunctionName b))
-> [NonEmpty (ComputedFieldMeta b)]
-> [(ComputedFieldName, FunctionName b)]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe ((ComputedFieldMeta b -> (ComputedFieldName, FunctionName b))
-> Maybe (ComputedFieldMeta b)
-> Maybe (ComputedFieldName, FunctionName b)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ((ComputedFieldMeta b -> ComputedFieldName)
-> (ComputedFieldMeta b -> FunctionName b)
-> ComputedFieldMeta b
-> (ComputedFieldName, FunctionName b)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
(&&&) ComputedFieldMeta b -> ComputedFieldName
forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName ComputedFieldMeta b -> FunctionName b
forall {b :: BackendType}. ComputedFieldMeta b -> FunctionName b
getFunction) (Maybe (ComputedFieldMeta b)
 -> Maybe (ComputedFieldName, FunctionName b))
-> (NonEmpty (ComputedFieldMeta b) -> Maybe (ComputedFieldMeta b))
-> NonEmpty (ComputedFieldMeta b)
-> Maybe (ComputedFieldName, FunctionName b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. NonEmpty (ComputedFieldMeta b) -> Maybe (ComputedFieldMeta b)
forall {a}. NonEmpty a -> Maybe a
getSecondElement)
            ([NonEmpty (ComputedFieldMeta b)]
 -> [(ComputedFieldName, FunctionName b)])
-> [NonEmpty (ComputedFieldMeta b)]
-> [(ComputedFieldName, FunctionName b)]
forall a b. (a -> b) -> a -> b
$ ((ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
 -> [ComputedFieldMeta b] -> [NonEmpty (ComputedFieldMeta b)])
-> [ComputedFieldMeta b]
-> (ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
-> [NonEmpty (ComputedFieldMeta b)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
-> [ComputedFieldMeta b] -> [NonEmpty (ComputedFieldMeta b)]
forall (f :: * -> *) a.
Foldable f =>
(a -> a -> Bool) -> f a -> [NonEmpty a]
NE.groupBy [ComputedFieldMeta b]
newComputedFieldMeta
            ((ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
 -> [NonEmpty (ComputedFieldMeta b)])
-> (ComputedFieldMeta b -> ComputedFieldMeta b -> Bool)
-> [NonEmpty (ComputedFieldMeta b)]
forall a b. (a -> b) -> a -> b
$ \ComputedFieldMeta b
l ComputedFieldMeta b
r ->
              ComputedFieldMeta b -> ComputedFieldName
forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName ComputedFieldMeta b
l ComputedFieldName -> ComputedFieldName -> Bool
forall a. Eq a => a -> a -> Bool
== ComputedFieldMeta b -> ComputedFieldName
forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName ComputedFieldMeta b
r Bool -> Bool -> Bool
&& ComputedFieldMeta b -> FunctionName b
forall {b :: BackendType}. ComputedFieldMeta b -> FunctionName b
getFunction ComputedFieldMeta b
l FunctionName b -> FunctionName b -> Bool
forall a. Eq a => a -> a -> Bool
== ComputedFieldMeta b -> FunctionName b
forall {b :: BackendType}. ComputedFieldMeta b -> FunctionName b
getFunction ComputedFieldMeta b
r

    computedFieldDiff :: ComputedFieldDiff b
computedFieldDiff =
      [ComputedFieldName]
-> [(ComputedFieldMeta b, ComputedFieldMeta b)]
-> [(ComputedFieldName, FunctionName b)]
-> ComputedFieldDiff b
forall (b :: BackendType).
[ComputedFieldName]
-> [(ComputedFieldMeta b, ComputedFieldMeta b)]
-> [(ComputedFieldName, FunctionName b)]
-> ComputedFieldDiff b
ComputedFieldDiff
        [ComputedFieldName]
droppedComputedFields
        [(ComputedFieldMeta b, ComputedFieldMeta b)]
alteredComputedFields
        [(ComputedFieldName, FunctionName b)]
overloadedComputedFieldFunctions

getTableChangeDeps ::
  forall b m.
  (QErrM m, CacheRM m, Backend b) =>
  SourceName ->
  TableName b ->
  TableDiff b ->
  m [SchemaObjId]
getTableChangeDeps :: forall (b :: BackendType) (m :: * -> *).
(QErrM m, CacheRM m, Backend b) =>
SourceName -> TableName b -> TableDiff b -> m [SchemaObjId]
getTableChangeDeps SourceName
source TableName b
tn TableDiff b
tableDiff = do
  SchemaCache
sc <- m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  -- for all the dropped columns
  [SchemaObjId]
droppedColDeps <- ([[SchemaObjId]] -> [SchemaObjId])
-> m [[SchemaObjId]] -> m [SchemaObjId]
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[SchemaObjId]] -> [SchemaObjId]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    (m [[SchemaObjId]] -> m [SchemaObjId])
-> m [[SchemaObjId]] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ [Column b] -> (Column b -> m [SchemaObjId]) -> m [[SchemaObjId]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Column b]
droppedCols
    ((Column b -> m [SchemaObjId]) -> m [[SchemaObjId]])
-> (Column b -> m [SchemaObjId]) -> m [[SchemaObjId]]
forall a b. (a -> b) -> a -> b
$ \Column b
droppedCol -> do
      let objId :: SchemaObjId
objId =
            SourceName -> AnyBackend SourceObjId -> SchemaObjId
SOSourceObj SourceName
source
              (AnyBackend SourceObjId -> SchemaObjId)
-> AnyBackend SourceObjId -> SchemaObjId
forall a b. (a -> b) -> a -> b
$ SourceObjId b -> AnyBackend SourceObjId
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
              (SourceObjId b -> AnyBackend SourceObjId)
-> SourceObjId b -> AnyBackend SourceObjId
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType).
TableName b -> TableObjId b -> SourceObjId b
SOITableObj @b TableName b
tn
              (TableObjId b -> SourceObjId b) -> TableObjId b -> SourceObjId b
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType). Column b -> TableObjId b
TOCol @b Column b
droppedCol
      [SchemaObjId] -> m [SchemaObjId]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([SchemaObjId] -> m [SchemaObjId])
-> [SchemaObjId] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ SchemaCache -> SchemaObjId -> [SchemaObjId]
getDependentObjs SchemaCache
sc SchemaObjId
objId
  -- for all dropped constraints
  [SchemaObjId]
droppedConsDeps <- ([[SchemaObjId]] -> [SchemaObjId])
-> m [[SchemaObjId]] -> m [SchemaObjId]
forall a b. (a -> b) -> m a -> m b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap [[SchemaObjId]] -> [SchemaObjId]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    (m [[SchemaObjId]] -> m [SchemaObjId])
-> m [[SchemaObjId]] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ [ConstraintName b]
-> (ConstraintName b -> m [SchemaObjId]) -> m [[SchemaObjId]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [ConstraintName b]
droppedFKeyConstraints
    ((ConstraintName b -> m [SchemaObjId]) -> m [[SchemaObjId]])
-> (ConstraintName b -> m [SchemaObjId]) -> m [[SchemaObjId]]
forall a b. (a -> b) -> a -> b
$ \ConstraintName b
droppedCons -> do
      let objId :: SchemaObjId
objId =
            SourceName -> AnyBackend SourceObjId -> SchemaObjId
SOSourceObj SourceName
source
              (AnyBackend SourceObjId -> SchemaObjId)
-> AnyBackend SourceObjId -> SchemaObjId
forall a b. (a -> b) -> a -> b
$ SourceObjId b -> AnyBackend SourceObjId
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
              (SourceObjId b -> AnyBackend SourceObjId)
-> SourceObjId b -> AnyBackend SourceObjId
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType).
TableName b -> TableObjId b -> SourceObjId b
SOITableObj @b TableName b
tn
              (TableObjId b -> SourceObjId b) -> TableObjId b -> SourceObjId b
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType). ConstraintName b -> TableObjId b
TOForeignKey @b ConstraintName b
droppedCons
      [SchemaObjId] -> m [SchemaObjId]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([SchemaObjId] -> m [SchemaObjId])
-> [SchemaObjId] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ SchemaCache -> SchemaObjId -> [SchemaObjId]
getDependentObjs SchemaCache
sc SchemaObjId
objId
  [SchemaObjId] -> m [SchemaObjId]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ([SchemaObjId] -> m [SchemaObjId])
-> [SchemaObjId] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ [SchemaObjId]
droppedConsDeps [SchemaObjId] -> [SchemaObjId] -> [SchemaObjId]
forall a. Semigroup a => a -> a -> a
<> [SchemaObjId]
droppedColDeps [SchemaObjId] -> [SchemaObjId] -> [SchemaObjId]
forall a. Semigroup a => a -> a -> a
<> [SchemaObjId]
droppedComputedFieldDeps
  where
    TableDiff Maybe (TableName b)
_ [Column b]
droppedCols [(RawColumnInfo b, RawColumnInfo b)]
_ [ConstraintName b]
droppedFKeyConstraints ComputedFieldDiff b
computedFieldDiff [ConstraintName b]
_ Maybe PGDescription
_ = TableDiff b
tableDiff
    droppedComputedFieldDeps :: [SchemaObjId]
droppedComputedFieldDeps =
      (ComputedFieldName -> SchemaObjId)
-> [ComputedFieldName] -> [SchemaObjId]
forall a b. (a -> b) -> [a] -> [b]
map
        ( SourceName -> AnyBackend SourceObjId -> SchemaObjId
SOSourceObj SourceName
source
            (AnyBackend SourceObjId -> SchemaObjId)
-> (ComputedFieldName -> AnyBackend SourceObjId)
-> ComputedFieldName
-> SchemaObjId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourceObjId b -> AnyBackend SourceObjId
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
            (SourceObjId b -> AnyBackend SourceObjId)
-> (ComputedFieldName -> SourceObjId b)
-> ComputedFieldName
-> AnyBackend SourceObjId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: BackendType).
TableName b -> TableObjId b -> SourceObjId b
SOITableObj @b TableName b
tn
            (TableObjId b -> SourceObjId b)
-> (ComputedFieldName -> TableObjId b)
-> ComputedFieldName
-> SourceObjId b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldName -> TableObjId b
forall (b :: BackendType). ComputedFieldName -> TableObjId b
TOComputedField
        )
        ([ComputedFieldName] -> [SchemaObjId])
-> [ComputedFieldName] -> [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ ComputedFieldDiff b -> [ComputedFieldName]
forall (b :: BackendType).
ComputedFieldDiff b -> [ComputedFieldName]
_cfdDropped ComputedFieldDiff b
computedFieldDiff

data TablesDiff (b :: BackendType) = TablesDiff
  { forall (b :: BackendType). TablesDiff b -> [TableName b]
_sdDroppedTables :: [TableName b],
    forall (b :: BackendType).
TablesDiff b -> [(TableName b, TableDiff b)]
_sdAlteredTables :: [(TableName b, TableDiff b)]
  }

getTablesDiff ::
  (Backend b) => [TableMeta b] -> [TableMeta b] -> TablesDiff b
getTablesDiff :: forall (b :: BackendType).
Backend b =>
[TableMeta b] -> [TableMeta b] -> TablesDiff b
getTablesDiff [TableMeta b]
oldMeta [TableMeta b]
newMeta =
  [TableName b] -> [(TableName b, TableDiff b)] -> TablesDiff b
forall (b :: BackendType).
[TableName b] -> [(TableName b, TableDiff b)] -> TablesDiff b
TablesDiff [TableName b]
droppedTables [(TableName b, TableDiff b)]
survivingTables
  where
    droppedTables :: [TableName b]
droppedTables = (TableMeta b -> TableName b) -> [TableMeta b] -> [TableName b]
forall a b. (a -> b) -> [a] -> [b]
map TableMeta b -> TableName b
forall (b :: BackendType). TableMeta b -> TableName b
tmTable ([TableMeta b] -> [TableName b]) -> [TableMeta b] -> [TableName b]
forall a b. (a -> b) -> a -> b
$ (TableMeta b -> OID)
-> [TableMeta b] -> [TableMeta b] -> [TableMeta b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn (DBTableMetadata b -> OID
forall (b :: BackendType). DBTableMetadata b -> OID
_ptmiOid (DBTableMetadata b -> OID)
-> (TableMeta b -> DBTableMetadata b) -> TableMeta b -> OID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo) [TableMeta b]
oldMeta [TableMeta b]
newMeta
    survivingTables :: [(TableName b, TableDiff b)]
survivingTables =
      (((TableMeta b, TableMeta b) -> (TableName b, TableDiff b))
 -> [(TableMeta b, TableMeta b)] -> [(TableName b, TableDiff b)])
-> [(TableMeta b, TableMeta b)]
-> ((TableMeta b, TableMeta b) -> (TableName b, TableDiff b))
-> [(TableName b, TableDiff b)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((TableMeta b, TableMeta b) -> (TableName b, TableDiff b))
-> [(TableMeta b, TableMeta b)] -> [(TableName b, TableDiff b)]
forall a b. (a -> b) -> [a] -> [b]
map ((TableMeta b -> OID)
-> [TableMeta b] -> [TableMeta b] -> [(TableMeta b, TableMeta b)]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [(v, v)]
getOverlapWith (DBTableMetadata b -> OID
forall (b :: BackendType). DBTableMetadata b -> OID
_ptmiOid (DBTableMetadata b -> OID)
-> (TableMeta b -> DBTableMetadata b) -> TableMeta b -> OID
forall b c a. (b -> c) -> (a -> b) -> a -> c
. TableMeta b -> DBTableMetadata b
forall (b :: BackendType). TableMeta b -> DBTableMetadata b
tmInfo) [TableMeta b]
oldMeta [TableMeta b]
newMeta) (((TableMeta b, TableMeta b) -> (TableName b, TableDiff b))
 -> [(TableName b, TableDiff b)])
-> ((TableMeta b, TableMeta b) -> (TableName b, TableDiff b))
-> [(TableName b, TableDiff b)]
forall a b. (a -> b) -> a -> b
$ \(TableMeta b
oldtm, TableMeta b
newtm) ->
        (TableMeta b -> TableName b
forall (b :: BackendType). TableMeta b -> TableName b
tmTable TableMeta b
oldtm, TableMeta b -> TableMeta b -> TableDiff b
forall (b :: BackendType).
Backend b =>
TableMeta b -> TableMeta b -> TableDiff b
getTableDiff TableMeta b
oldtm TableMeta b
newtm)

getIndirectDependenciesFromTableDiff ::
  forall b m.
  (QErrM m, CacheRM m, Backend b) =>
  SourceName ->
  TablesDiff b ->
  m [SchemaObjId]
getIndirectDependenciesFromTableDiff :: forall (b :: BackendType) (m :: * -> *).
(QErrM m, CacheRM m, Backend b) =>
SourceName -> TablesDiff b -> m [SchemaObjId]
getIndirectDependenciesFromTableDiff SourceName
source TablesDiff b
tablesDiff = do
  SchemaCache
sc <- m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  let tableIds :: [SchemaObjId]
tableIds = SourceName -> AnyBackend SourceObjId -> SchemaObjId
SOSourceObj SourceName
source (AnyBackend SourceObjId -> SchemaObjId)
-> (TableName b -> AnyBackend SourceObjId)
-> TableName b
-> SchemaObjId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourceObjId b -> AnyBackend SourceObjId
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend (SourceObjId b -> AnyBackend SourceObjId)
-> (TableName b -> SourceObjId b)
-> TableName b
-> AnyBackend SourceObjId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (b :: BackendType). TableName b -> SourceObjId b
SOITable @b (TableName b -> SchemaObjId) -> [TableName b] -> [SchemaObjId]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> [TableName b]
droppedTables
      tableDropDeps :: [SchemaObjId]
tableDropDeps = (SchemaObjId -> [SchemaObjId]) -> [SchemaObjId] -> [SchemaObjId]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (SchemaCache -> SchemaObjId -> [SchemaObjId]
getDependentObjs SchemaCache
sc) [SchemaObjId]
tableIds
  [SchemaObjId]
tableModDeps <- [[SchemaObjId]] -> [SchemaObjId]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([[SchemaObjId]] -> [SchemaObjId])
-> m [[SchemaObjId]] -> m [SchemaObjId]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ((TableName b, TableDiff b) -> m [SchemaObjId])
-> [(TableName b, TableDiff b)] -> m [[SchemaObjId]]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> [a] -> f [b]
traverse ((TableName b -> TableDiff b -> m [SchemaObjId])
-> (TableName b, TableDiff b) -> m [SchemaObjId]
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry (SourceName -> TableName b -> TableDiff b -> m [SchemaObjId]
forall (b :: BackendType) (m :: * -> *).
(QErrM m, CacheRM m, Backend b) =>
SourceName -> TableName b -> TableDiff b -> m [SchemaObjId]
getTableChangeDeps SourceName
source)) [(TableName b, TableDiff b)]
alteredTables
  [SchemaObjId] -> m [SchemaObjId]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ([SchemaObjId] -> m [SchemaObjId])
-> [SchemaObjId] -> m [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ (SchemaObjId -> Bool) -> [SchemaObjId] -> [SchemaObjId]
forall a. (a -> Bool) -> [a] -> [a]
filter SchemaObjId -> Bool
isIndirectDep ([SchemaObjId] -> [SchemaObjId]) -> [SchemaObjId] -> [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ HashSet SchemaObjId -> [SchemaObjId]
forall a. HashSet a -> [a]
HS.toList (HashSet SchemaObjId -> [SchemaObjId])
-> HashSet SchemaObjId -> [SchemaObjId]
forall a b. (a -> b) -> a -> b
$ [SchemaObjId] -> HashSet SchemaObjId
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList ([SchemaObjId] -> HashSet SchemaObjId)
-> [SchemaObjId] -> HashSet SchemaObjId
forall a b. (a -> b) -> a -> b
$ [SchemaObjId]
tableDropDeps [SchemaObjId] -> [SchemaObjId] -> [SchemaObjId]
forall a. Semigroup a => a -> a -> a
<> [SchemaObjId]
tableModDeps
  where
    TablesDiff [TableName b]
droppedTables [(TableName b, TableDiff b)]
alteredTables = TablesDiff b
tablesDiff
    -- we keep all table objects that are not tied to a deleted table
    isIndirectDep :: SchemaObjId -> Bool
    isIndirectDep :: SchemaObjId -> Bool
isIndirectDep = \case
      -- table objects in the same source
      SOSourceObj SourceName
s AnyBackend SourceObjId
obj
        | SourceName
s SourceName -> SourceName -> Bool
forall a. Eq a => a -> a -> Bool
== SourceName
source,
          Just (SOITableObj TableName b
tn TableObjId b
_) <- forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
AnyBackend i -> Maybe (i b)
AB.unpackAnyBackend @b AnyBackend SourceObjId
obj ->
            Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ TableName b
tn TableName b -> HashSet (TableName b) -> Bool
forall a. (Eq a, Hashable a) => a -> HashSet a -> Bool
`HS.member` [TableName b] -> HashSet (TableName b)
forall a. (Eq a, Hashable a) => [a] -> HashSet a
HS.fromList [TableName b]
droppedTables
      -- table objects in any other source
      SOSourceObj SourceName
_ AnyBackend SourceObjId
obj ->
        AnyBackend SourceObjId
-> (forall (b :: BackendType). SourceObjId b -> Bool) -> Bool
forall (i :: BackendType -> *) r.
AnyBackend i -> (forall (b :: BackendType). i b -> r) -> r
AB.runBackend AnyBackend SourceObjId
obj \case
          SOITableObj {} -> Bool
True
          SourceObjId b
_ -> Bool
False
      -- any other kind of schema object
      SchemaObjId
_ -> Bool
False

data FunctionsDiff b = FunctionsDiff
  { forall (b :: BackendType). FunctionsDiff b -> [FunctionName b]
fdDropped :: [FunctionName b],
    forall (b :: BackendType).
FunctionsDiff b -> [(FunctionName b, FunctionVolatility)]
fdAltered :: [(FunctionName b, FunctionVolatility)]
  }

deriving instance (Backend b) => Show (FunctionsDiff b)

deriving instance (Backend b) => Eq (FunctionsDiff b)

getFunctionsDiff :: [FunctionMeta b] -> [FunctionMeta b] -> FunctionsDiff b
getFunctionsDiff :: forall (b :: BackendType).
[FunctionMeta b] -> [FunctionMeta b] -> FunctionsDiff b
getFunctionsDiff [FunctionMeta b]
oldMeta [FunctionMeta b]
newMeta =
  [FunctionName b]
-> [(FunctionName b, FunctionVolatility)] -> FunctionsDiff b
forall (b :: BackendType).
[FunctionName b]
-> [(FunctionName b, FunctionVolatility)] -> FunctionsDiff b
FunctionsDiff [FunctionName b]
droppedFuncs [(FunctionName b, FunctionVolatility)]
alteredFuncs
  where
    droppedFuncs :: [FunctionName b]
droppedFuncs = (FunctionMeta b -> FunctionName b)
-> [FunctionMeta b] -> [FunctionName b]
forall a b. (a -> b) -> [a] -> [b]
map FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction ([FunctionMeta b] -> [FunctionName b])
-> [FunctionMeta b] -> [FunctionName b]
forall a b. (a -> b) -> a -> b
$ (FunctionMeta b -> OID)
-> [FunctionMeta b] -> [FunctionMeta b] -> [FunctionMeta b]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [v]
getDifferenceOn FunctionMeta b -> OID
forall (b :: BackendType). FunctionMeta b -> OID
fmOid [FunctionMeta b]
oldMeta [FunctionMeta b]
newMeta
    alteredFuncs :: [(FunctionName b, FunctionVolatility)]
alteredFuncs = ((FunctionMeta b, FunctionMeta b)
 -> Maybe (FunctionName b, FunctionVolatility))
-> [(FunctionMeta b, FunctionMeta b)]
-> [(FunctionName b, FunctionVolatility)]
forall a b. (a -> Maybe b) -> [a] -> [b]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (FunctionMeta b, FunctionMeta b)
-> Maybe (FunctionName b, FunctionVolatility)
forall {b :: BackendType} {b :: BackendType}.
(FunctionMeta b, FunctionMeta b)
-> Maybe (FunctionName b, FunctionVolatility)
mkAltered ([(FunctionMeta b, FunctionMeta b)]
 -> [(FunctionName b, FunctionVolatility)])
-> [(FunctionMeta b, FunctionMeta b)]
-> [(FunctionName b, FunctionVolatility)]
forall a b. (a -> b) -> a -> b
$ (FunctionMeta b -> OID)
-> [FunctionMeta b]
-> [FunctionMeta b]
-> [(FunctionMeta b, FunctionMeta b)]
forall k v. Hashable k => (v -> k) -> [v] -> [v] -> [(v, v)]
getOverlapWith FunctionMeta b -> OID
forall (b :: BackendType). FunctionMeta b -> OID
fmOid [FunctionMeta b]
oldMeta [FunctionMeta b]
newMeta
    mkAltered :: (FunctionMeta b, FunctionMeta b)
-> Maybe (FunctionName b, FunctionVolatility)
mkAltered (FunctionMeta b
oldfm, FunctionMeta b
newfm) =
      let isTypeAltered :: Bool
isTypeAltered = FunctionMeta b -> FunctionVolatility
forall (b :: BackendType). FunctionMeta b -> FunctionVolatility
fmType FunctionMeta b
oldfm FunctionVolatility -> FunctionVolatility -> Bool
forall a. Eq a => a -> a -> Bool
/= FunctionMeta b -> FunctionVolatility
forall (b :: BackendType). FunctionMeta b -> FunctionVolatility
fmType FunctionMeta b
newfm
          alteredFunc :: (FunctionName b, FunctionVolatility)
alteredFunc = (FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction FunctionMeta b
oldfm, FunctionMeta b -> FunctionVolatility
forall (b :: BackendType). FunctionMeta b -> FunctionVolatility
fmType FunctionMeta b
newfm)
       in Maybe (FunctionName b, FunctionVolatility)
-> Maybe (FunctionName b, FunctionVolatility)
-> Bool
-> Maybe (FunctionName b, FunctionVolatility)
forall a. a -> a -> Bool -> a
bool Maybe (FunctionName b, FunctionVolatility)
forall a. Maybe a
Nothing ((FunctionName b, FunctionVolatility)
-> Maybe (FunctionName b, FunctionVolatility)
forall a. a -> Maybe a
Just (FunctionName b, FunctionVolatility)
alteredFunc) Bool
isTypeAltered

getOverloadedFunctions ::
  (Backend b) => [FunctionName b] -> [FunctionMeta b] -> [FunctionName b]
getOverloadedFunctions :: forall (b :: BackendType).
Backend b =>
[FunctionName b] -> [FunctionMeta b] -> [FunctionName b]
getOverloadedFunctions [FunctionName b]
trackedFuncs [FunctionMeta b]
newFuncMeta =
  HashSet (FunctionName b) -> [FunctionName b]
forall a. HashSet a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (HashSet (FunctionName b) -> [FunctionName b])
-> HashSet (FunctionName b) -> [FunctionName b]
forall a b. (a -> b) -> a -> b
$ [FunctionName b] -> HashSet (FunctionName b)
forall a. Hashable a => [a] -> HashSet a
duplicates ([FunctionName b] -> HashSet (FunctionName b))
-> [FunctionName b] -> HashSet (FunctionName b)
forall a b. (a -> b) -> a -> b
$ (FunctionMeta b -> FunctionName b)
-> [FunctionMeta b] -> [FunctionName b]
forall a b. (a -> b) -> [a] -> [b]
map FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction [FunctionMeta b]
trackedMeta
  where
    trackedMeta :: [FunctionMeta b]
trackedMeta = ((FunctionMeta b -> Bool) -> [FunctionMeta b] -> [FunctionMeta b])
-> [FunctionMeta b] -> (FunctionMeta b -> Bool) -> [FunctionMeta b]
forall a b c. (a -> b -> c) -> b -> a -> c
flip (FunctionMeta b -> Bool) -> [FunctionMeta b] -> [FunctionMeta b]
forall a. (a -> Bool) -> [a] -> [a]
filter [FunctionMeta b]
newFuncMeta ((FunctionMeta b -> Bool) -> [FunctionMeta b])
-> (FunctionMeta b -> Bool) -> [FunctionMeta b]
forall a b. (a -> b) -> a -> b
$ \FunctionMeta b
fm ->
      FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction FunctionMeta b
fm FunctionName b -> [FunctionName b] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FunctionName b]
trackedFuncs

processTablesDiff ::
  forall b m.
  ( MonadError QErr m,
    CacheRM m,
    MonadWriter MetadataModifier m,
    BackendMetadata b
  ) =>
  SourceName ->
  TableCache b ->
  TablesDiff b ->
  m ()
processTablesDiff :: forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName -> TableCache b -> TablesDiff b -> m ()
processTablesDiff SourceName
source TableCache b
preActionTables TablesDiff b
tablesDiff = do
  -- Purge the dropped tables
  forall (b :: BackendType) (m :: * -> *).
(MonadWriter MetadataModifier m, BackendMetadata b) =>
SourceName -> [TableName b] -> m ()
dropTablesInMetadata @b SourceName
source [TableName b]
droppedTables

  [(TableName b, TableDiff b)]
-> ((TableName b, TableDiff b) -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [(TableName b, TableDiff b)]
alteredTables (((TableName b, TableDiff b) -> m ()) -> m ())
-> ((TableName b, TableDiff b) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \(TableName b
oldQtn, TableDiff b
tableDiff) -> do
    TableInfo b
ti <-
      Maybe (TableInfo b) -> m (TableInfo b) -> m (TableInfo b)
forall (m :: * -> *) a. Applicative m => Maybe a -> m a -> m a
onNothing
        (TableName b -> TableCache b -> Maybe (TableInfo b)
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> Maybe v
HashMap.lookup TableName b
oldQtn TableCache b
preActionTables)
        (Text -> m (TableInfo b)
forall (m :: * -> *) a. QErrM m => Text -> m a
throw500 (Text -> m (TableInfo b)) -> Text -> m (TableInfo b)
forall a b. (a -> b) -> a -> b
$ Text
"old table metadata not found in cache: " Text -> TableName b -> Text
forall t. ToTxt t => Text -> t -> Text
<>> TableName b
oldQtn)
    SourceName -> TableCoreInfo b -> TableDiff b -> m ()
forall (m :: * -> *) (b :: BackendType).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName -> TableCoreInfo b -> TableDiff b -> m ()
alterTableInMetadata SourceName
source (TableInfo b -> TableCoreInfo b
forall (b :: BackendType). TableInfo b -> TableCoreInfo b
_tiCoreInfo TableInfo b
ti) TableDiff b
tableDiff
  where
    TablesDiff [TableName b]
droppedTables [(TableName b, TableDiff b)]
alteredTables = TablesDiff b
tablesDiff

alterTableInMetadata ::
  forall m b.
  ( MonadError QErr m,
    CacheRM m,
    MonadWriter MetadataModifier m,
    BackendMetadata b
  ) =>
  SourceName ->
  TableCoreInfo b ->
  TableDiff b ->
  m ()
alterTableInMetadata :: forall (m :: * -> *) (b :: BackendType).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName -> TableCoreInfo b -> TableDiff b -> m ()
alterTableInMetadata SourceName
source TableCoreInfo b
ti TableDiff b
tableDiff = do
  -- If table rename occurs then don't replace constraints and
  -- process dropped/added columns, because schema reload happens eventually
  SchemaCache
sc <- m SchemaCache
forall (m :: * -> *). CacheRM m => m SchemaCache
askSchemaCache
  let tn :: TableName b
tn = TableCoreInfo b -> TableName b
forall (b :: BackendType) field primaryKeyColumn.
TableCoreInfoG b field primaryKeyColumn -> TableName b
_tciName TableCoreInfo b
ti
      withOldTabName :: m ()
withOldTabName = do
        SourceName
-> [(RawColumnInfo b, RawColumnInfo b)]
-> FieldInfoMap (FieldInfo b)
-> SchemaCache
-> TableName b
-> m ()
forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName
-> [(RawColumnInfo b, RawColumnInfo b)]
-> FieldInfoMap (FieldInfo b)
-> SchemaCache
-> TableName b
-> m ()
alterColumnsInMetadata SourceName
source [(RawColumnInfo b, RawColumnInfo b)]
alteredCols FieldInfoMap (FieldInfo b)
tableFields SchemaCache
sc TableName b
tn

      withNewTabName :: TableName b -> m ()
      withNewTabName :: TableName b -> m ()
withNewTabName TableName b
newTN = do
        -- check for GraphQL schema conflicts on new name
        Either QErr Name -> m Name
forall e (m :: * -> *) a. MonadError e m => Either e a -> m a
liftEither (forall (b :: BackendType).
Backend b =>
TableName b -> Either QErr Name
tableGraphQLName @b TableName b
newTN) m Name -> (Name -> m ()) -> m ()
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= SchemaCache -> Text -> m ()
forall (m :: * -> *).
MonadError QErr m =>
SchemaCache -> Text -> m ()
checkConflictingNode SchemaCache
sc (Text -> m ()) -> (Name -> Text) -> Name -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Name -> Text
G.unName
        SourceName
-> [(RawColumnInfo b, RawColumnInfo b)]
-> FieldInfoMap (FieldInfo b)
-> SchemaCache
-> TableName b
-> m ()
forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName
-> [(RawColumnInfo b, RawColumnInfo b)]
-> FieldInfoMap (FieldInfo b)
-> SchemaCache
-> TableName b
-> m ()
alterColumnsInMetadata SourceName
source [(RawColumnInfo b, RawColumnInfo b)]
alteredCols FieldInfoMap (FieldInfo b)
tableFields SchemaCache
sc TableName b
tn
        -- update new table in metadata
        forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName -> TableName b -> TableName b -> m ()
renameTableInMetadata @b SourceName
source TableName b
newTN TableName b
tn

  -- Process computed field diff
  TableName b -> m ()
processComputedFieldDiff TableName b
tn
  -- Drop custom column names and comments for dropped columns
  SourceName -> [Column b] -> TableCoreInfo b -> m ()
forall (b :: BackendType) (m :: * -> *).
(MonadWriter MetadataModifier m, BackendMetadata b) =>
SourceName -> [Column b] -> TableCoreInfo b -> m ()
removeDroppedColumnsFromMetadataField SourceName
source [Column b]
droppedCols TableCoreInfo b
ti
  m () -> (TableName b -> m ()) -> Maybe (TableName b) -> m ()
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m ()
withOldTabName TableName b -> m ()
withNewTabName Maybe (TableName b)
mNewName
  where
    TableDiff Maybe (TableName b)
mNewName [Column b]
droppedCols [(RawColumnInfo b, RawColumnInfo b)]
alteredCols [ConstraintName b]
_ ComputedFieldDiff b
computedFieldDiff [ConstraintName b]
_ Maybe PGDescription
_ = TableDiff b
tableDiff
    tableFields :: FieldInfoMap (FieldInfo b)
tableFields = TableCoreInfo b -> FieldInfoMap (FieldInfo b)
forall (b :: BackendType) field primaryKeyColumn.
TableCoreInfoG b field primaryKeyColumn -> FieldInfoMap field
_tciFieldInfoMap TableCoreInfo b
ti

    processComputedFieldDiff :: TableName b -> m ()
    processComputedFieldDiff :: TableName b -> m ()
processComputedFieldDiff TableName b
table = do
      let ComputedFieldDiff [ComputedFieldName]
_ [(ComputedFieldMeta b, ComputedFieldMeta b)]
altered [(ComputedFieldName, FunctionName b)]
overloaded = ComputedFieldDiff b
computedFieldDiff
          getFunction :: ComputedFieldMeta b -> FunctionName b
getFunction = FunctionMeta b -> FunctionName b
forall (b :: BackendType). FunctionMeta b -> FunctionName b
fmFunction (FunctionMeta b -> FunctionName b)
-> (ComputedFieldMeta b -> FunctionMeta b)
-> ComputedFieldMeta b
-> FunctionName b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldMeta b -> FunctionMeta b
forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta
      [(ComputedFieldName, FunctionName b)]
-> ((ComputedFieldName, FunctionName b) -> m Any) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ComputedFieldName, FunctionName b)]
overloaded (((ComputedFieldName, FunctionName b) -> m Any) -> m ())
-> ((ComputedFieldName, FunctionName b) -> m Any) -> m ()
forall a b. (a -> b) -> a -> b
$ \(ComputedFieldName
columnName, FunctionName b
function) ->
        Code -> Text -> m Any
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported
          (Text -> m Any) -> Text -> m Any
forall a b. (a -> b) -> a -> b
$ Text
"The function "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> FunctionName b
function
          FunctionName b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" associated with computed field"
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ComputedFieldName
columnName
          ComputedFieldName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" of table "
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TableName b
table
          TableName b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" is being overloaded"
      [(ComputedFieldMeta b, ComputedFieldMeta b)]
-> ((ComputedFieldMeta b, ComputedFieldMeta b) -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [(ComputedFieldMeta b, ComputedFieldMeta b)]
altered (((ComputedFieldMeta b, ComputedFieldMeta b) -> m ()) -> m ())
-> ((ComputedFieldMeta b, ComputedFieldMeta b) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \(ComputedFieldMeta b
old, ComputedFieldMeta b
new) ->
        if
          | (FunctionMeta b -> FunctionVolatility
forall (b :: BackendType). FunctionMeta b -> FunctionVolatility
fmType (FunctionMeta b -> FunctionVolatility)
-> (ComputedFieldMeta b -> FunctionMeta b)
-> ComputedFieldMeta b
-> FunctionVolatility
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ComputedFieldMeta b -> FunctionMeta b
forall (b :: BackendType). ComputedFieldMeta b -> FunctionMeta b
ccmFunctionMeta) ComputedFieldMeta b
new FunctionVolatility -> FunctionVolatility -> Bool
forall a. Eq a => a -> a -> Bool
== FunctionVolatility
FTVOLATILE ->
              Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
NotSupported
                (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"The type of function "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ComputedFieldMeta b -> FunctionName b
forall {b :: BackendType}. ComputedFieldMeta b -> FunctionName b
getFunction ComputedFieldMeta b
old
                FunctionName b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" associated with computed field "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> ComputedFieldMeta b -> ComputedFieldName
forall (b :: BackendType). ComputedFieldMeta b -> ComputedFieldName
ccmName ComputedFieldMeta b
old
                ComputedFieldName -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" of table "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TableName b
table
                TableName b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" is being altered to \"VOLATILE\""
          | Bool
otherwise -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

dropTablesInMetadata ::
  forall b m.
  ( MonadWriter MetadataModifier m,
    BackendMetadata b
  ) =>
  SourceName ->
  [TableName b] ->
  m ()
dropTablesInMetadata :: forall (b :: BackendType) (m :: * -> *).
(MonadWriter MetadataModifier m, BackendMetadata b) =>
SourceName -> [TableName b] -> m ()
dropTablesInMetadata SourceName
source [TableName b]
droppedTables =
  [TableName b] -> (TableName b -> m ()) -> m ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [TableName b]
droppedTables
    ((TableName b -> m ()) -> m ()) -> (TableName b -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \TableName b
tn -> MetadataModifier -> m ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell (MetadataModifier -> m ()) -> MetadataModifier -> m ()
forall a b. (a -> b) -> a -> b
$ (Metadata -> Metadata) -> MetadataModifier
MetadataModifier ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ (Sources -> Identity Sources) -> Metadata -> Identity Metadata
Lens' Metadata Sources
metaSources ((Sources -> Identity Sources) -> Metadata -> Identity Metadata)
-> ((InsOrdHashMap (TableName b) (TableMetadata b)
     -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
    -> Sources -> Identity Sources)
-> (InsOrdHashMap (TableName b) (TableMetadata b)
    -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Index Sources -> Traversal' Sources (IxValue Sources)
forall m. Ixed m => Index m -> Traversal' m (IxValue m)
ix Index Sources
SourceName
source ((BackendSourceMetadata -> Identity BackendSourceMetadata)
 -> Sources -> Identity Sources)
-> ((InsOrdHashMap (TableName b) (TableMetadata b)
     -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
    -> BackendSourceMetadata -> Identity BackendSourceMetadata)
-> (InsOrdHashMap (TableName b) (TableMetadata b)
    -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
-> Sources
-> Identity Sources
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (SourceMetadata b -> Identity (SourceMetadata b))
-> BackendSourceMetadata -> Identity BackendSourceMetadata
forall (b :: BackendType).
Backend b =>
Prism' BackendSourceMetadata (SourceMetadata b)
Prism' BackendSourceMetadata (SourceMetadata b)
toSourceMetadata ((SourceMetadata b -> Identity (SourceMetadata b))
 -> BackendSourceMetadata -> Identity BackendSourceMetadata)
-> ((InsOrdHashMap (TableName b) (TableMetadata b)
     -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
    -> SourceMetadata b -> Identity (SourceMetadata b))
-> (InsOrdHashMap (TableName b) (TableMetadata b)
    -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
-> BackendSourceMetadata
-> Identity BackendSourceMetadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (forall (b :: BackendType) (f :: * -> *).
Functor f =>
(Tables b -> f (Tables b))
-> SourceMetadata b -> f (SourceMetadata b)
smTables @b) ((InsOrdHashMap (TableName b) (TableMetadata b)
  -> Identity (InsOrdHashMap (TableName b) (TableMetadata b)))
 -> Metadata -> Identity Metadata)
-> (InsOrdHashMap (TableName b) (TableMetadata b)
    -> InsOrdHashMap (TableName b) (TableMetadata b))
-> Metadata
-> Metadata
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ TableName b
-> InsOrdHashMap (TableName b) (TableMetadata b)
-> InsOrdHashMap (TableName b) (TableMetadata b)
forall k v.
(Eq k, Hashable k) =>
k -> InsOrdHashMap k v -> InsOrdHashMap k v
InsOrdHashMap.delete TableName b
tn

alterColumnsInMetadata ::
  forall b m.
  ( MonadError QErr m,
    CacheRM m,
    MonadWriter MetadataModifier m,
    BackendMetadata b
  ) =>
  SourceName ->
  [(RawColumnInfo b, RawColumnInfo b)] ->
  FieldInfoMap (FieldInfo b) ->
  SchemaCache ->
  TableName b ->
  m ()
alterColumnsInMetadata :: forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
SourceName
-> [(RawColumnInfo b, RawColumnInfo b)]
-> FieldInfoMap (FieldInfo b)
-> SchemaCache
-> TableName b
-> m ()
alterColumnsInMetadata SourceName
source [(RawColumnInfo b, RawColumnInfo b)]
alteredCols FieldInfoMap (FieldInfo b)
fields SchemaCache
sc TableName b
tn =
  [(RawColumnInfo b, RawColumnInfo b)]
-> ((RawColumnInfo b, RawColumnInfo b) -> m ()) -> m ()
forall (t :: * -> *) (f :: * -> *) a b.
(Foldable t, Applicative f) =>
t a -> (a -> f b) -> f ()
for_ [(RawColumnInfo b, RawColumnInfo b)]
alteredCols
    (((RawColumnInfo b, RawColumnInfo b) -> m ()) -> m ())
-> ((RawColumnInfo b, RawColumnInfo b) -> m ()) -> m ()
forall a b. (a -> b) -> a -> b
$ \( RawColumnInfo {rciName :: forall (b :: BackendType). RawColumnInfo b -> Column b
rciName = Column b
oldName, rciType :: forall (b :: BackendType). RawColumnInfo b -> RawColumnType b
rciType = RawColumnType b
oldType},
         RawColumnInfo {rciName :: forall (b :: BackendType). RawColumnInfo b -> Column b
rciName = Column b
newName, rciType :: forall (b :: BackendType). RawColumnInfo b -> RawColumnType b
rciType = RawColumnType b
newType}
         ) -> do
        if
          | Column b
oldName Column b -> Column b -> Bool
forall a. Eq a => a -> a -> Bool
/= Column b
newName ->
              Column b
-> Column b
-> SourceName
-> TableName b
-> FieldInfoMap (FieldInfo b)
-> m ()
forall (b :: BackendType) (m :: * -> *).
(MonadError QErr m, CacheRM m, MonadWriter MetadataModifier m,
 BackendMetadata b) =>
Column b
-> Column b
-> SourceName
-> TableName b
-> FieldInfoMap (FieldInfo b)
-> m ()
renameColumnInMetadata Column b
oldName Column b
newName SourceName
source TableName b
tn FieldInfoMap (FieldInfo b)
fields
          | RawColumnType b
oldType RawColumnType b -> RawColumnType b -> Bool
forall a. Eq a => a -> a -> Bool
/= RawColumnType b
newType -> do
              let colId :: SchemaObjId
colId =
                    SourceName -> AnyBackend SourceObjId -> SchemaObjId
SOSourceObj SourceName
source
                      (AnyBackend SourceObjId -> SchemaObjId)
-> AnyBackend SourceObjId -> SchemaObjId
forall a b. (a -> b) -> a -> b
$ SourceObjId b -> AnyBackend SourceObjId
forall (b :: BackendType) (i :: BackendType -> *).
HasTag b =>
i b -> AnyBackend i
AB.mkAnyBackend
                      (SourceObjId b -> AnyBackend SourceObjId)
-> SourceObjId b -> AnyBackend SourceObjId
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType).
TableName b -> TableObjId b -> SourceObjId b
SOITableObj @b TableName b
tn
                      (TableObjId b -> SourceObjId b) -> TableObjId b -> SourceObjId b
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType). Column b -> TableObjId b
TOCol @b Column b
oldName
                  typeDepObjs :: [SchemaObjId]
typeDepObjs = (DependencyReason -> Bool)
-> SchemaCache -> SchemaObjId -> [SchemaObjId]
getDependentObjsWith (DependencyReason -> DependencyReason -> Bool
forall a. Eq a => a -> a -> Bool
== DependencyReason
DROnType) SchemaCache
sc SchemaObjId
colId

              Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless ([SchemaObjId] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [SchemaObjId]
typeDepObjs)
                (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ Code -> Text -> m ()
forall (m :: * -> *) a. QErrM m => Code -> Text -> m a
throw400 Code
DependencyError
                (Text -> m ()) -> Text -> m ()
forall a b. (a -> b) -> a -> b
$ Text
"cannot change type of column "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Column b
oldName
                Column b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" in table "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> TableName b
tn
                TableName b -> Text -> Text
forall t. ToTxt t => t -> Text -> Text
<<> Text
" because of the following dependencies: "
                Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> [SchemaObjId] -> Text
reportSchemaObjs [SchemaObjId]
typeDepObjs
          | Bool
otherwise -> () -> m ()
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ()

removeDroppedColumnsFromMetadataField ::
  forall b m.
  (MonadWriter MetadataModifier m, BackendMetadata b) =>
  SourceName ->
  [Column b] ->
  TableCoreInfo b ->
  m ()
removeDroppedColumnsFromMetadataField :: forall (b :: BackendType) (m :: * -> *).
(MonadWriter MetadataModifier m, BackendMetadata b) =>
SourceName -> [Column b] -> TableCoreInfo b -> m ()
removeDroppedColumnsFromMetadataField SourceName
source [Column b]
droppedCols TableCoreInfo b
tableInfo = do
  Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (HashMap (Column b) ColumnConfig
newColumnConfig HashMap (Column b) ColumnConfig
-> HashMap (Column b) ColumnConfig -> Bool
forall a. Eq a => a -> a -> Bool
/= HashMap (Column b) ColumnConfig
originalColumnConfig)
    (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ MetadataModifier -> m ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell
    (MetadataModifier -> m ()) -> MetadataModifier -> m ()
forall a b. (a -> b) -> a -> b
$ (Metadata -> Metadata) -> MetadataModifier
MetadataModifier
    ((Metadata -> Metadata) -> MetadataModifier)
-> (Metadata -> Metadata) -> MetadataModifier
forall a b. (a -> b) -> a -> b
$ forall (b :: BackendType).
Backend b =>
SourceName -> TableName b -> ASetter' Metadata (TableMetadata b)
tableMetadataSetter @b SourceName
source TableName b
tableName
    ASetter' Metadata (TableMetadata b)
-> ((TableConfig b -> Identity (TableConfig b))
    -> TableMetadata b -> Identity (TableMetadata b))
-> (TableConfig b -> Identity (TableConfig b))
-> Metadata
-> Identity Metadata
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (TableConfig b -> Identity (TableConfig b))
-> TableMetadata b -> Identity (TableMetadata b)
forall (b :: BackendType) (f :: * -> *).
Functor f =>
(TableConfig b -> f (TableConfig b))
-> TableMetadata b -> f (TableMetadata b)
tmConfiguration
    ((TableConfig b -> Identity (TableConfig b))
 -> Metadata -> Identity Metadata)
-> TableConfig b -> Metadata -> Metadata
forall s t a b. ASetter s t a b -> b -> s -> t
.~ TableConfig b
newTableConfig
  where
    tableName :: TableName b
tableName = TableCoreInfo b -> TableName b
forall (b :: BackendType) field primaryKeyColumn.
TableCoreInfoG b field primaryKeyColumn -> TableName b
_tciName TableCoreInfo b
tableInfo
    originalTableConfig :: TableConfig b
originalTableConfig = TableCoreInfo b -> TableConfig b
forall (b :: BackendType) field primaryKeyColumn.
TableCoreInfoG b field primaryKeyColumn -> TableConfig b
_tciCustomConfig TableCoreInfo b
tableInfo
    originalColumnConfig :: HashMap (Column b) ColumnConfig
originalColumnConfig = TableConfig b -> HashMap (Column b) ColumnConfig
forall (b :: BackendType).
TableConfig b -> HashMap (Column b) ColumnConfig
_tcColumnConfig TableConfig b
originalTableConfig
    newColumnConfig :: HashMap (Column b) ColumnConfig
newColumnConfig = (HashMap (Column b) ColumnConfig
 -> Column b -> HashMap (Column b) ColumnConfig)
-> HashMap (Column b) ColumnConfig
-> [Column b]
-> HashMap (Column b) ColumnConfig
forall b a. (b -> a -> b) -> b -> [a] -> b
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' ((Column b
 -> HashMap (Column b) ColumnConfig
 -> HashMap (Column b) ColumnConfig)
-> HashMap (Column b) ColumnConfig
-> Column b
-> HashMap (Column b) ColumnConfig
forall a b c. (a -> b -> c) -> b -> a -> c
flip Column b
-> HashMap (Column b) ColumnConfig
-> HashMap (Column b) ColumnConfig
forall k v. (Eq k, Hashable k) => k -> HashMap k v -> HashMap k v
HashMap.delete) HashMap (Column b) ColumnConfig
originalColumnConfig [Column b]
droppedCols
    newTableConfig :: TableConfig b
newTableConfig = TableConfig b
originalTableConfig TableConfig b -> (TableConfig b -> TableConfig b) -> TableConfig b
forall a b. a -> (a -> b) -> b
& (HashMap (Column b) ColumnConfig
 -> Identity (HashMap (Column b) ColumnConfig))
-> TableConfig b -> Identity (TableConfig b)
forall (b1 :: BackendType) (b2 :: BackendType) (f :: * -> *).
Functor f =>
(HashMap (Column b1) ColumnConfig
 -> f (HashMap (Column b2) ColumnConfig))
-> TableConfig b1 -> f (TableConfig b2)
tcColumnConfig ((HashMap (Column b) ColumnConfig
  -> Identity (HashMap (Column b) ColumnConfig))
 -> TableConfig b -> Identity (TableConfig b))
-> HashMap (Column b) ColumnConfig
-> TableConfig b
-> TableConfig b
forall s t a b. ASetter s t a b -> b -> s -> t
.~ HashMap (Column b) ColumnConfig
newColumnConfig