@@ -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