Skip to content

Commit 3e9e642

Browse files
committed
Implement predicateRestrictsDropOf
1 parent 80be5ea commit 3e9e642

File tree

3 files changed

+28
-9
lines changed

3 files changed

+28
-9
lines changed

beam-migrate/Database/Beam/Migrate/Actions.hs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,9 @@ dropColumnProvider = ActionProvider provider
408408
-- TableHasColumn tblNm' colNm' colType' :: TableHasColumn (Sql92DdlCommandColumnSchemaSyntax cmd) <-
409409
-- findPostConditions
410410
-- guard (tblNm' == tblNm && colNm == colNm' && colType == colType') -- This column exists as a different type
411+
ensuringNot_ $ do
412+
SomeDatabasePredicate pred' <- findPreConditions
413+
guard (pred' `predicateRestrictsDropOf` colP)
411414

412415
relatedPreds <- --pure []
413416
pure $ do p'@(SomeDatabasePredicate pred') <- findPreConditions

beam-migrate/Database/Beam/Migrate/Checks.hs

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,24 +5,28 @@
55
-- | Defines common 'DatabasePredicate's that are shared among backends
66
module Database.Beam.Migrate.Checks where
77

8+
import Control.Monad (guard)
9+
810
import Database.Beam.Migrate.Serialization
911
import Database.Beam.Migrate.Types.Predicates
1012
import Database.Beam.Migrate.SQL.SQL92
1113
import Database.Beam.Schema.Indices
1214
import Database.Beam.Schema.Tables
1315

16+
import Data.Proxy (Proxy (..))
1417
import Data.Aeson ((.:), (.=), withObject, object)
1518
import Data.Aeson.Types (Parser, Value)
1619
import Data.Hashable (Hashable(..))
1720
import Data.Text (Text)
18-
import Data.Typeable (Typeable, cast)
21+
import Data.Typeable (typeOf, splitTyConApp, typeRep, Typeable, cast)
1922
#if !MIN_VERSION_base(4, 11, 0)
2023
import Data.Semigroup
2124
#endif
2225

2326
import GHC.Generics (Generic)
2427
import GHC.Exts (fromList, toList)
2528

29+
import Unsafe.Coerce (unsafeCoerce)
2630

2731
-- * Table checks
2832

@@ -152,12 +156,24 @@ instance DatabasePredicate TableHasIndex where
152156
| Just (TableExistsPredicate tblNm') <- cast p' = tblNm' == tblNm
153157
| otherwise = False
154158

155-
-- TODO: how to say that we cannot delete a column while an index on it exists?
156-
-- The following does not work since 'TableHasColumn' is polymorphic other used syntax, and
157-
-- we don't know which index to get here
158-
--
159-
-- predicateRestrictDropOf (TableHasIndex tblNm _) p'
160-
-- | Just (TableHasColumn tblNm' _ _) <- cast p' = tblNm' == tblNm
159+
predicateRestrictsDropOf (TableHasIndex tblNm colNms _) p'
160+
| Just (tblNm', colNm') <-
161+
withTyCon (\(TableHasColumn tblNm' colNm' _) -> (tblNm', colNm')) p' =
162+
tblNm == tblNm' && (colNm' `elem` colNms)
163+
| otherwise = False
164+
165+
-- | Match a given item's type against a type-level application with the given
166+
-- type constructor. Applies the given function and returns 'Just' its result on match,
167+
-- 'Nothing' otherwise.
168+
withTyCon
169+
:: forall (con :: * -> *) (item :: *) r.
170+
(Typeable con, Typeable item)
171+
=> (forall c. con c -> r) -> item -> Maybe r
172+
withTyCon f x = do
173+
let (tyItemCon, _) = splitTyConApp $ typeRep (Proxy @item)
174+
(tyCon, _) = splitTyConApp (typeOf x)
175+
guard (tyItemCon == tyCon)
176+
return (f $ unsafeCoerce x)
161177

162178
-- | Convert gathered indices into checks.
163179
entityIndicesToChecks

beam-migrate/Database/Beam/Migrate/Types/Predicates.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,8 +47,8 @@ class (Typeable p, Hashable p, Eq p) => DatabasePredicate p where
4747
-- needs another one to be true in order to exist. The difference is, the other
4848
-- predicate cannot be removed until this one exists, this predicate has to be
4949
-- explicitely removed with a corresponding action first.
50-
predicateRestrictDropOf :: DatabasePredicate p' => p -> p' -> Bool
51-
predicateRestrictDropOf _ _ = False
50+
predicateRestrictsDropOf :: DatabasePredicate p' => p -> p' -> Bool
51+
predicateRestrictsDropOf _ _ = False
5252

5353
-- | A Database predicate is a value of any type which satisfies
5454
-- 'DatabasePredicate'. We often want to store these in lists and sets, so we

0 commit comments

Comments
 (0)