@@ -94,11 +94,11 @@ import Safe
9494-- custom migration tags in the changelog, as generated by
9595-- 'generateMigrationKind'.
9696
97- migrateDataDump :: (Read db , Read rec , Read fld )
97+ migrateDataDump :: (Read db , Read rec , Read alt , Read fld )
9898 => (API , Version ) -- ^ Starting schema and version
9999 -> (API , VersionExtra ) -- ^ Ending schema and version
100100 -> APIChangelog -- ^ Log of changes, containing both versions
101- -> CustomMigrations JS. Object JS. Value db rec fld -- ^ Custom migration functions
101+ -> CustomMigrations JS. Object JS. Value db rec alt fld -- ^ Custom migration functions
102102 -> TypeName -- ^ Name of the dataset's type
103103 -> DataChecks -- ^ How thoroughly to validate changes
104104 -> JS. Value -- ^ Dataset to be migrated
@@ -110,11 +110,11 @@ migrateDataDump startApi endApi changelog custom root chks db = do
110110 db' <- applyChangesToDatabase root custom' db changes ?!? uncurry ValueError
111111 return (db', warnings)
112112
113- migrateDataDump' :: (Read db , Read rec , Read fld )
113+ migrateDataDump' :: (Read db , Read rec , Read alt , Read fld )
114114 => (API , Version ) -- ^ Starting schema and version
115115 -> (API , VersionExtra ) -- ^ Ending schema and version
116116 -> APIChangelog -- ^ Log of changes, containing both versions
117- -> CustomMigrations Record Value db rec fld -- ^ Custom migration functions
117+ -> CustomMigrations Record Value db rec alt fld -- ^ Custom migration functions
118118 -> TypeName -- ^ Name of the dataset's type
119119 -> DataChecks -- ^ How thoroughly to validate changes
120120 -> Value. Value -- ^ Dataset to be migrated
@@ -129,36 +129,41 @@ migrateDataDump' startApi endApi changelog custom root chks db = do
129129
130130
131131-- | Custom migrations used in the changelog must be implemented in
132- -- Haskell, and supplied in this record. There are three kinds:
132+ -- Haskell, and supplied in this record. There are four kinds:
133133--
134134-- * Whole-database migrations, which may arbitrarily change the API
135135-- schema and the data to match;
136136--
137- -- * Type migrations, which may change the schema of a single type; and
137+ -- * Type migrations, which may change the schema of a single type;
138+ --
139+ -- * Union alternative migrations, which may change the type of a
140+ -- single alternative within a union (with the new type specified in
141+ -- the changelog); and
138142--
139143-- * Single field migrations, which may change only the type of the
140144-- field (with the new type specified in the changelog).
141145--
142146-- For database and type migrations, if the schema is unchanged, the
143147-- corresponding function should return 'Nothing'.
144148--
145- -- The @db@, @ty@ and @fld@ parameters should be instantiated with
146- -- the enumeration types generated by 'generateMigrationKinds', which
147- -- correspond to the exact set of custom migration tags used in the
148- -- changelog.
149- data CustomMigrations o v db ty fld = CustomMigrations
149+ -- The @db@, @ty@, @alt@ and @fld@ parameters should be instantiated
150+ -- with the enumeration types generated by 'generateMigrationKinds',
151+ -- which correspond to the exact set of custom migration tags used in
152+ -- the changelog.
153+ data CustomMigrations o v db ty alt fld = CustomMigrations
150154 { databaseMigration :: db -> o -> Either ValueError o
151155 , databaseMigrationSchema :: db -> NormAPI -> Either ApplyFailure (Maybe NormAPI )
152156 , typeMigration :: ty -> v -> Either ValueError v
153157 , typeMigrationSchema :: ty -> NormTypeDecl -> Either ApplyFailure (Maybe NormTypeDecl )
158+ , unionAltMigration :: alt -> v -> Either ValueError v
154159 , fieldMigration :: fld -> v -> Either ValueError v }
155160
156- type CustomMigrationsTagged o v = CustomMigrations o v MigrationTag MigrationTag MigrationTag
161+ type CustomMigrationsTagged o v = CustomMigrations o v MigrationTag MigrationTag MigrationTag MigrationTag
157162
158- readCustomMigrations :: (Read db , Read ty , Read fld )
159- => CustomMigrations o v db ty fld -> CustomMigrationsTagged o v
160- readCustomMigrations (CustomMigrations db dbs r rs f) =
161- CustomMigrations (db . read ) (dbs . read ) (r . read ) (rs . read ) (f . read )
163+ readCustomMigrations :: (Read db , Read ty , Read alt , Read fld )
164+ => CustomMigrations o v db ty alt fld -> CustomMigrationsTagged o v
165+ readCustomMigrations (CustomMigrations db dbs r rs a f) =
166+ CustomMigrations (db . read ) (dbs . read ) (r . read ) (rs . read ) (a . read ) ( f . read )
162167
163168-- | Lift a custom record migration to work on arbitrary values
164169mkRecordMigration :: (JS. Object -> Either ValueError JS. Object )
@@ -244,23 +249,23 @@ isChangelogOrdered changelog =
244249
245250
246251-- | Sets of custom migration tags in the changelog for
247- -- whole-database, single-record and single-field migrations
248- changelogTags :: APIChangelog -> (Set MigrationTag , Set MigrationTag , Set MigrationTag )
249- changelogTags (ChangesStart _) = (Set. empty, Set. empty, Set. empty)
252+ -- whole-database, single-type, union-alternative and single-field migrations
253+ changelogTags :: APIChangelog -> (Set MigrationTag , Set MigrationTag , Set MigrationTag , Set MigrationTag )
254+ changelogTags (ChangesStart _) = (Set. empty, Set. empty, Set. empty, Set. empty )
250255changelogTags (ChangesUpTo _ cs older) =
251- unions3 (map changeTags cs) `union3 ` changelogTags older
256+ unions4 (map changeTags cs) `union4 ` changelogTags older
252257 where
253- union3 (a, b, c) (x, y, z) = (a `Set.union` x, b `Set.union` y, c `Set.union` z)
254- unions3 xyzs = (Set. unions xs, Set. unions ys, Set. unions zs)
255- where (xs, ys, zs) = unzip3 xyzs
258+ union4 (a, b, c, d ) (x, y, z, w ) = (a `Set.union` x, b `Set.union` y, c `Set.union` z, d `Set.union` w )
259+ unions4 xyzws = (Set. unions xs, Set. unions ys, Set. unions zs, Set. unions ws )
260+ where (xs, ys, zs, ws ) = unzip4 xyzws
256261
257262-- | Sets of custom migration tags in a single change
258- changeTags :: APIChange -> (Set MigrationTag , Set MigrationTag , Set MigrationTag )
259- changeTags (ChChangeField _ _ _ t) = (Set. empty, Set. empty, Set. singleton t)
260- changeTags (ChChangeUnionAlt _ _ _ t) = (Set. empty, Set. singleton t, Set. empty)
261- changeTags (ChCustomType _ t) = (Set. empty, Set. singleton t, Set. empty)
262- changeTags (ChCustomAll t) = (Set. singleton t, Set. empty, Set. empty)
263- changeTags _ = (Set. empty, Set. empty, Set. empty)
263+ changeTags :: APIChange -> (Set MigrationTag , Set MigrationTag , Set MigrationTag , Set MigrationTag )
264+ changeTags (ChChangeField _ _ _ t) = (Set. empty, Set. empty, Set. empty, Set. singleton t)
265+ changeTags (ChChangeUnionAlt _ _ _ t) = (Set. empty, Set. empty, Set. singleton t, Set. empty)
266+ changeTags (ChCustomType _ t) = (Set. empty, Set. singleton t, Set. empty, Set. empty )
267+ changeTags (ChCustomAll t) = (Set. singleton t, Set. empty, Set. empty, Set. empty )
268+ changeTags _ = (Set. empty, Set. empty, Set. empty, Set. empty )
264269
265270
266271--------------------------------
@@ -306,11 +311,11 @@ findUpdatePos tname api = Map.alter (Just . UpdateHere) tname $
306311
307312-- | Check that a changelog adequately describes how to migrate from
308313-- one version to another.
309- validateChanges :: (Read db , Read rec , Read fld )
314+ validateChanges :: (Read db , Read rec , Read alt , Read fld )
310315 => (API , Version ) -- ^ Starting schema and version
311316 -> (API , VersionExtra ) -- ^ Ending schema and version
312317 -> APIChangelog -- ^ Changelog to be validated
313- -> CustomMigrations o v db rec fld -- ^ Custom migration functions
318+ -> CustomMigrations o v db rec alt fld -- ^ Custom migration functions
314319 -> TypeName -- ^ Name of the dataset's type
315320 -> DataChecks -- ^ How thoroughly to validate changes
316321 -> Either ValidateFailure [ValidateWarning ]
@@ -620,7 +625,7 @@ applyChangeToData (ChRenameUnionAlt _ fname fname') _ = withObject $ \un p ->
620625applyChangeToData (ChChangeUnionAlt _ fname _ftype tag) custom = withObject $ \ un p ->
621626 case matchSingletonObject un of
622627 Just (k, r) | k == _FieldName fname -> do
623- r' <- liftMigration (typeMigration custom tag) r p
628+ r' <- liftMigration (unionAltMigration custom tag) r p
624629 return $ singletonObject (_FieldName fname) r'
625630 _ -> return un
626631
@@ -738,7 +743,7 @@ applyChangeToData' _ (ChRenameUnionAlt _ fname fname') _ v p = do
738743applyChangeToData' _ (ChChangeUnionAlt _ fname _ftype tag) custom v p = do
739744 (fn, v') <- expectUnion v p
740745 if fn == fname
741- then Union fn <$!> liftMigration (typeMigration custom tag) v' (inField fn: p)
746+ then Union fn <$!> liftMigration (unionAltMigration custom tag) v' (inField fn: p)
742747 else pure v
743748
744749applyChangeToData' _ (ChRenameEnumVal _ fname fname') _ v p = do
@@ -887,17 +892,21 @@ type Decode t = JS.Value -> Either [(JSONError, Position)] t
887892
888893-- | Generate enumeration datatypes corresponding to the custom
889894-- migrations used in an API migration changelog.
890- generateMigrationKinds :: APIChangelog -> String -> String -> String -> Q [Dec ]
891- generateMigrationKinds changes all_nm rec_nm fld_nm = do
895+ generateMigrationKinds :: APIChangelog -> String -> String -> String -> String -> Q [Dec ]
896+ generateMigrationKinds changes all_nm rec_nm alt_nm fld_nm = do
892897 guardNoDups (all_tags `Set.intersection` rec_tags)
898+ guardNoDups (all_tags `Set.intersection` alt_tags)
893899 guardNoDups (all_tags `Set.intersection` fld_tags)
900+ guardNoDups (rec_tags `Set.intersection` alt_tags)
894901 guardNoDups (rec_tags `Set.intersection` fld_tags)
902+ guardNoDups (alt_tags `Set.intersection` fld_tags)
895903
896904 return [ mkDataD [] (mkName all_nm) [] (cons all_nm all_tags) derivs
897905 , mkDataD [] (mkName rec_nm) [] (cons rec_nm rec_tags) derivs
906+ , mkDataD [] (mkName alt_nm) [] (cons alt_nm alt_tags) derivs
898907 , mkDataD [] (mkName fld_nm) [] (cons fld_nm fld_tags) derivs ]
899908 where
900- (all_tags, rec_tags, fld_tags) = changelogTags changes
909+ (all_tags, rec_tags, alt_tags, fld_tags) = changelogTags changes
901910
902911 guardNoDups xs
903912 | Set. null xs = return ()
0 commit comments