on master help sign in
fix confusing error message when creating incdep where the expressions do not have equal relation types

resolves #181 Conflicts: src/lib/ProjectM36/RelationalExpression.hs

commitaf1821ef41c373a804549b9253a15ed8dc65d616 authorAgentM <agentm@themactionfaction.com> dateThu 28 Dec 2017, 22:02 (9 years ago) parent54e1e99
5 files changed+23−19
docs/tutd_tutorial.markdown+1−1 src/lib/ProjectM36/Error.hs+1−1 src/lib/ProjectM36/RelationalExpression.hs+18−14 src/lib/ProjectM36/TransactionGraph.hs+2−2 test/Client/Simple.hs+1−1
docs/tutd_tutorial.markdown+1−1
@@ -489,7 +489,7 @@ Foreign keys are constraints which require that certain values appearing in one
489489TutorialD (master/main): foreign key s#_in_sp sp{s#} in s{s#}
490490```
491491
492−This expression ensure that any sp{s#} must also appear as a value in s{s#}.
492+This expression ensure that any sp{s#} must also appear as a value in s{s#}. Note that the sub-expression (on the left of "in") and the super-expression (on the right) must be of the same relation type- the generated relation values' attribute names and types must be equal. Use `rename` to make attribute names identical.
493493
494494#### Functional dependencies
495495
src/lib/ProjectM36/Error.hs+1−1
@@ -22,7 +22,7 @@ data RelationalError = NoSuchAttributeNamesError (S.Set AttributeName)
2222 | CouldNotInferAttributes
2323 | RelVarNotDefinedError RelVarName
2424 | RelVarAlreadyDefinedError RelVarName
25− | RelVarAssignmentTypeMismatchError Attributes Attributes --expected, found
25+ | RelationTypeMismatchError Attributes Attributes --expected, found
2626 | InclusionDependencyCheckError IncDepName
2727 | InclusionDependencyNameInUseError IncDepName
2828 | InclusionDependencyNameNotInUseError IncDepName
src/lib/ProjectM36/RelationalExpression.hs+18−14
@@ -235,8 +235,8 @@ setRelVar relVarName rel = do
235235 potentialContext = currentContext { relationVariables = newRelVars }
236236
237237 case checkConstraints potentialContext of
238− Just err -> return $ Just err
239− Nothing -> do
238+ Left err -> pure (Just err)
239+ Right _ -> do
240240 putStateContext potentialContext
241241 return Nothing
242242
@@ -286,7 +286,7 @@ evalDatabaseContextExpr (Assign relVarName expr) = do
286286 if A.attributesEqual expectedAttributes foundAttributes then
287287 setRelVar relVarName rel
288288 else
289− return $ Just (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes)
289+ pure (Just (RelationTypeMismatchError expectedAttributes foundAttributes))
290290
291291evalDatabaseContextExpr (Insert relVarName relExpr) = do
292292 context <- getStateContext
@@ -350,8 +350,8 @@ evalDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
350350 else do
351351 let potentialContext = currContext { inclusionDependencies = newDeps }
352352 case checkConstraints potentialContext of
353− Just err -> return $ Just err
354− Nothing -> do
353+ Left err -> pure (Just err)
354+ Right _ -> do
355355 putStateContext potentialContext
356356 return Nothing
357357
@@ -566,22 +566,26 @@ updateTupleWithAtomExprs exprMap context tupIn = do
566566 pure (updateTupleWithAtoms (M.fromList atomsAssoc) tupIn)
567567
568568--run verification on all constraints
569−checkConstraints :: DatabaseContext -> Maybe RelationalError
570−checkConstraints context = case failures of
571− [] -> Nothing
572− l:_ -> Just l
569+checkConstraints :: DatabaseContext -> Either RelationalError ()
570+checkConstraints context = do
571+ mapM_ (uncurry checkIncDep) (M.toList deps)
572+ pure ()
573573 where
574− failures = M.elems $ M.mapMaybeWithKey checkIncDep deps
575574 deps = inclusionDependencies context
576− eval expr = runReader (evalRelationalExpr expr) (RelationalExprStateElems context)
575+ eval expr = evalReader (evalRelationalExpr expr)
576+ evalReader f = runReader f (RelationalExprStateElems context)
577577 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = do
578+ --if both expressions are of a single-attribute (such as with a simple foreign key), the names of the attributes are irrelevant (they need not match) because the expression is unambiguous, but special-casing this to rename the attribute automatically would not be orthogonal behavior and probably cause confusion. Instead, special case the error to make it clear.
579+ typeSub <- evalReader (typeForRelationalExpr subsetExpr)
580+ typeSuper <- evalReader (typeForRelationalExpr supersetExpr)
581+ when (typeSub /= typeSuper) (Left (RelationTypeMismatchError (attributes typeSub) (attributes typeSuper)))
578582 let checkExpr = Equals supersetExpr (Union subsetExpr supersetExpr)
579583 case eval checkExpr of
580− Left err -> Just err
584+ Left err -> Left err
581585 Right resultRel -> if resultRel == relationTrue then
582− Nothing
586+ pure ()
583587 else
584− Just $ InclusionDependencyCheckError depName
588+ Left (InclusionDependencyCheckError depName)
585589
586590-- the type of a relational expression is equal to the relation attribute set returned from executing the relational expression; therefore, the type can be cheaply derived by evaluating a relational expression and ignoring and tuple processing
587591-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
src/lib/ProjectM36/TransactionGraph.hs+2−2
@@ -407,8 +407,8 @@ mergeTransactions stamp newId parentId mergeStrategy (headNameA, headNameB) grap
407407 case createMergeTransaction stamp newId mergeStrategy subGraph' (transA, transB) of
408408 Left err -> Left (MergeTransactionError err)
409409 Right mergedTrans -> case checkConstraints (concreteDatabaseContext mergedTrans) of
410− Just err -> Left err
411− Nothing -> case headNameForTransaction disconParent graph of
410+ Left err -> Left err
411+ Right _ -> case headNameForTransaction disconParent graph of
412412 Nothing -> Left (TransactionIsNotAHeadError parentId)
413413 Just headName -> do
414414 (newTrans, newGraph) <- addTransactionToGraph headName mergedTrans graph
test/Client/Simple.hs+1−1
@@ -55,7 +55,7 @@ testSimpleCommitFailure = TestCase $ do
5555 execute $ Assign "x" (ExistingRelation relationTrue)
5656 --cause error
5757 execute $ Assign "x" (MakeStaticRelation failAttrs emptyTupleSet)
58− let expectedErr = Left (RelError (RelVarAssignmentTypeMismatchError V.empty failAttrs))
58+ let expectedErr = Left (RelError (RelationTypeMismatchError V.empty failAttrs))
5959 assertEqual "dbc error" expectedErr err
6060
6161