@@ -3,7 +3,6 @@ module ProjectM36.IsomorphicSchema where
33import ProjectM36.Base
44import ProjectM36.Error
55import ProjectM36.RelationalExpression
6−import Data.Maybe
76import Control.Monad
87import Control.Monad.State
98import GHC.Generics
@@ -26,18 +25,9 @@ data SchemaExpr = AddSubschema SchemaName |
2625 RemoveSubschema SchemaName
2726 deriving (Generic, Binary)
2827
29−-- | Return True iff the SchemaIsomorph is fully isomorphic in the sense that it does not represent an isomorphic sub-schema.
30−isFullyIsomorphic :: SchemaIsomorph -> Bool
31−isFullyIsomorphic (IsoRestrict _ _ (a, b)) = isJust a && isJust b
32−isFullyIsomorphic (IsoUnion (_, a) _ _) = isJust a
33−
3428isomorphs :: Schema -> SchemaIsomorphs
3529isomorphs (Schema i) = i
3630
37−-- | Convenience function which renames a relvar in schemaA to another name in schemaB.
38−isomorphRename :: RelVarName -> RelVarName -> SchemaIsomorph
39−isomorphRename nameA nameB = IsoRestrict nameA TruePredicate (Just nameB, Nothing)
40−
4131{- -- useful for transforming a concrete context into a virtual schema and vice versa
4232invert :: SchemaIsomorph -> SchemaIsomorph
4333invert (IsoRelVarName nameA nameB) = IsoRelVarName nameB nameA
@@ -45,7 +35,7 @@ invert (IsoRelVarName nameA nameB) = IsoRelVarName nameB nameA
4535
4636isomorphInRelVarNames :: SchemaIsomorph -> [RelVarName]
4737isomorphInRelVarNames (IsoRestrict rv _ _) = [rv]
48−isomorphInRelVarNames (IsoUnion (rvA, mRvB) _ _) = rvA : maybe [] (\x -> [x]) mRvB
38+isomorphInRelVarNames (IsoUnion (rvA, rvB) _ _) = [rvA, rvB]
4939
5040-- | Relation variables names represented in the virtual schema space. Useful for determining if a relvar name is valid in the schema.
5141isomorphsInRelVarNames :: SchemaIsomorphs -> S.Set RelVarName
@@ -54,7 +44,7 @@ isomorphsInRelVarNames morphs = S.fromList (foldr rvnames [] morphs)
5444 rvnames morph acc = acc ++ isomorphInRelVarNames morph
5545
5646isomorphOutRelVarNames :: SchemaIsomorph -> [RelVarName]
57−isomorphOutRelVarNames (IsoRestrict _ _ (mRvA, mRvB)) = catMaybes [mRvA, mRvB]
47+isomorphOutRelVarNames (IsoRestrict _ _ (rvA, rvB)) = [rvA, rvB]
5848isomorphOutRelVarNames (IsoUnion _ _ rvA) = [rvA]
5949
6050isomorphsOutRelVarNames :: SchemaIsomorphs -> S.Set RelVarName
@@ -99,21 +89,14 @@ applySchemaToInclusionDependencies (Schema morphs) incDeps =
9989
10090-- | Morph a relational expression in one schema to another isomorphic schema.
10191relExprMorph :: SchemaIsomorph -> (RelationalExpr -> Either RelationalError RelationalExpr)
102−relExprMorph (IsoRestrict relIn predi split) = \expr -> case expr of
103− RelationVariable rv () | rv == relIn -> case split of
104− -- hide the relvarname
105− (Nothing, Nothing) -> Left (RelVarNotDefinedError rv)
106− --simple relvar rename
107− (Just relOutTrue, Nothing) -> Right (Restrict predi (RelationVariable relOutTrue ()))
108− --rename but always empty relation- is this useful?
109− (Nothing, Just relOutFalse) -> Right (Restrict (NotPredicate predi) (RelationVariable relOutFalse ()))
110− (Just relOutTrue, Just relOutFalse) -> Right (Union (RelationVariable relOutTrue ()) (RelationVariable relOutFalse ()))
92+relExprMorph (IsoRestrict relIn _ (relOutTrue, relOutFalse)) = \expr -> case expr of
93+ RelationVariable rv () | rv == relIn -> Right (Union (RelationVariable relOutTrue ()) (RelationVariable relOutFalse ()))
11194 orig -> Right orig
112−relExprMorph (IsoUnion (relInT, mRelInF) predi relTarget) = \expr -> case expr of
95+relExprMorph (IsoUnion (relInT, relInF) predi relTarget) = \expr -> case expr of
11396 --only the true predicate portion appears in the virtual schema
11497 RelationVariable rv () | rv == relInT -> Right (Restrict predi (RelationVariable relTarget ()))
11598
116− RelationVariable rv () | Just rv == mRelInF -> Right (Restrict (NotPredicate predi) (RelationVariable relTarget ()))
99+ RelationVariable rv () | rv == relInF -> Right (Restrict (NotPredicate predi) (RelationVariable relTarget ()))
117100 orig -> Right orig
118101
119102relExprMogrify :: (RelationalExpr -> Either RelationalError RelationalExpr) -> RelationalExpr -> Either RelationalError RelationalExpr
@@ -154,48 +137,36 @@ spam2 = relExprMogrify (relExprMorph (IsoUnion ("boss", Just "nonboss") TruePred
154137-}
155138
156139databaseContextExprMorph :: SchemaIsomorph -> (RelationalExpr -> Either RelationalError RelationalExpr) -> DatabaseContextExpr -> Either RelationalError DatabaseContextExpr
157−databaseContextExprMorph iso@(IsoRestrict rvIn filt split) relExprFunc expr = case expr of
140+databaseContextExprMorph iso@(IsoRestrict rvIn filt (rvTrue, rvFalse)) relExprFunc expr = case expr of
158141 Assign rv relExpr | rv == rvIn -> do
159142 ex <- relExprFunc relExpr
160143 let trueExpr n = Assign n (Restrict filt ex)
161144 falseExpr n = Assign n (Restrict (NotPredicate filt) ex)
162− case split of
163− (Just rvTrue, Just rvFalse) -> pure $ MultipleExpr [trueExpr rvTrue, falseExpr rvFalse]
164− (Just rvTrue, Nothing) -> pure (trueExpr rvTrue)
165− (Nothing, Just rvFalse) -> pure (falseExpr rvFalse)
166− (Nothing, Nothing) -> Left (RelVarNotDefinedError rvIn)
145+ pure $ MultipleExpr [trueExpr rvTrue, falseExpr rvFalse]
167146 Insert rv relExpr | rv == rvIn -> do
168147 ex <- relExprFunc relExpr
169148 let trueExpr n = Insert n (Restrict filt ex)
170149 falseExpr n = Insert n (Restrict (NotPredicate filt) ex)
171− case split of
172− (Just rvTrue, Just rvFalse) -> pure $ MultipleExpr [trueExpr rvTrue, falseExpr rvFalse]
173− (Just rvTrue, Nothing) -> pure (trueExpr rvTrue)
174− (Nothing, Just rvFalse) -> pure (falseExpr rvFalse)
175− (Nothing, Nothing) -> Left (RelVarNotDefinedError rvIn)
150+ pure $ MultipleExpr [trueExpr rvTrue, falseExpr rvFalse]
176151 Update rv attrMap predi | rv == rvIn -> do
177152 -- if the update would "shift" a tuple from the true->false relvar or vice versa, that would be a constraint violation in the virtual schema
178153 let trueExpr n = Update n attrMap (AndPredicate predi filt)
179154 falseExpr n = Update n attrMap (AndPredicate predi (NotPredicate filt))
180− case split of
181− (Just rvTrue, Just rvFalse) -> pure (MultipleExpr [trueExpr rvTrue, falseExpr rvFalse])
182− (Just rvTrue, Nothing) -> pure (trueExpr rvTrue)
183− (Nothing, Just rvFalse) -> pure (falseExpr rvFalse)
184− (Nothing, Nothing) -> Left (RelVarNotDefinedError rvIn)
155+ pure (MultipleExpr [trueExpr rvTrue, falseExpr rvFalse])
185156 MultipleExpr exprs -> MultipleExpr <$> mapM (databaseContextExprMorph iso relExprFunc) exprs
186157 orig -> pure orig
187−databaseContextExprMorph iso@(IsoUnion (rvTrue, mRvFalse) filt rvOut) relExprFunc expr = case expr of
158+databaseContextExprMorph (IsoUnion (rvTrue, rvFalse) filt rvOut) relExprFunc expr = case expr of
188159 --assign: replace all instances in the portion of the target relvar with the new tuples from the relExpr
189160 --problem: between the delete->insert, constraints could be violated which would not otherwise be violated in the "in" schema. This implies that there should be a combo operator which can insert/update/delete in a single pass based on relexpr queries, or perhaps MultipleExpr should be the infamous "comma" operator from TutorialD?
190161 Assign rv relExpr | rv == rvTrue -> relExprFunc relExpr >>= \ex -> pure $ MultipleExpr [Delete rvOut filt,
191162 Insert rvOut (Restrict filt ex)]
192− Assign rv relExpr | Just rv == mRvFalse -> relExprFunc relExpr >>= \ex -> pure $ MultipleExpr [Delete rvOut (NotPredicate filt),
193− Insert rvOut (Restrict (NotPredicate filt) ex)]
194− Insert rv relExpr | rv == rvTrue || Just rv == mRvFalse -> relExprFunc relExpr >>= \ex -> pure $ Insert rvOut ex
163+ Assign rv relExpr | rv == rvFalse -> relExprFunc relExpr >>= \ex -> pure $ MultipleExpr [Delete rvOut (NotPredicate filt),
164+ Insert rvOut (Restrict (NotPredicate filt) ex)]
165+ Insert rv relExpr | rv == rvTrue || rv == rvFalse -> relExprFunc relExpr >>= \ex -> pure $ Insert rvOut ex
195166 Delete rv delPred | rv == rvTrue -> pure $ Delete rvOut (AndPredicate delPred filt)
196− Delete rv delPred | Just rv == mRvFalse -> pure $ Delete rvOut (AndPredicate delPred (NotPredicate filt))
167+ Delete rv delPred | rv == rvFalse -> pure $ Delete rvOut (AndPredicate delPred (NotPredicate filt))
197168 Update rv attrMap predi | rv == rvTrue -> pure $ Update rvOut attrMap (AndPredicate predi filt)
198− Update rv attrMap predi | Just rv == mRvFalse -> pure $ Update rvOut attrMap (AndPredicate (NotPredicate filt) predi)
169+ Update rv attrMap predi | rv == rvFalse -> pure $ Update rvOut attrMap (AndPredicate (NotPredicate filt) predi)
199170 orig -> pure orig
200171
201172-- | Apply the isomorphism transformations to the relational expression to convert the relational expression from operating on one schema to a disparate, isomorphic schema.
@@ -207,13 +178,10 @@ inclusionDependenciesMorph iso = \(InclusionDependency subExpr expr) -> Inclusio
207178
208179applyInclusionDependenciesSchemaIsoMorphs :: SchemaIsomorphs -> InclusionDependencies -> Either RelationalError InclusionDependencies
209180--add inc deps for restriction with some automatic name
210−applyInclusionDependenciesSchemaIsoMorphs morphs incDeps = undefined
181+applyInclusionDependenciesSchemaIsoMorphs _ _ = undefined
211182
212183relationVariablesInSchema :: Schema -> DatabaseContext -> Either RelationalError RelationVariables
213−relationVariablesInSchema schema@(Schema morphs) context = if null morphs then --main schema
214− pure (relationVariables context)
215− else
216− foldM transform M.empty morphs
184+relationVariablesInSchema schema@(Schema morphs) context = foldM transform M.empty morphs
217185 where
218186 transform newRvMap morph = do
219187 let rvNames = isomorphInRelVarNames morph