@@ -244,8 +244,8 @@ setRelVar relVarName rel = do
244244 potentialContext = currentContext { relationVariables = newRelVars }
245245
246246 case checkConstraints potentialContext of
247− Just err -> pure (Left err)
248− Nothing -> do
247+ Left err -> pure (Left err)
248+ Right _ -> do
249249 putStateContext potentialContext
250250 return (Right ())
251251
@@ -295,7 +295,7 @@ evalDatabaseContextExpr (Assign relVarName expr) = do
295295 if A.attributesEqual expectedAttributes foundAttributes then
296296 setRelVar relVarName rel
297297 else
298− pure (Left (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes))
298+ pure (Left (RelationTypeMismatchError expectedAttributes foundAttributes))
299299
300300evalDatabaseContextExpr (Insert relVarName relExpr) = do
301301 context <- getStateContext
@@ -359,8 +359,8 @@ evalDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
359359 else do
360360 let potentialContext = currContext { inclusionDependencies = newDeps }
361361 case checkConstraints potentialContext of
362− Just err -> pure (Left err)
363− Nothing -> do
362+ Left err -> pure (Left err)
363+ Right _ -> do
364364 putStateContext potentialContext
365365 return (Right ())
366366
@@ -574,22 +574,26 @@ updateTupleWithAtomExprs exprMap context tupIn = do
574574 pure (updateTupleWithAtoms (M.fromList atomsAssoc) tupIn)
575575
576576--run verification on all constraints
577−checkConstraints :: DatabaseContext -> Maybe RelationalError
578−checkConstraints context = case failures of
579− [] -> Nothing
580− l:_ -> Just l
577+checkConstraints :: DatabaseContext -> Either RelationalError ()
578+checkConstraints context = do
579+ mapM_ (uncurry checkIncDep) (M.toList deps)
580+ pure ()
581581 where
582− failures = M.elems $ M.mapMaybeWithKey checkIncDep deps
583582 deps = inclusionDependencies context
584− eval expr = runReader (evalRelationalExpr expr) (RelationalExprStateElems context)
583+ eval expr = evalReader (evalRelationalExpr expr)
584+ evalReader f = runReader f (RelationalExprStateElems context)
585585 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = do
586+ --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.
587+ typeSub <- evalReader (typeForRelationalExpr subsetExpr)
588+ typeSuper <- evalReader (typeForRelationalExpr supersetExpr)
589+ when (typeSub /= typeSuper) (Left (RelationTypeMismatchError (attributes typeSub) (attributes typeSuper)))
586590 let checkExpr = Equals supersetExpr (Union subsetExpr supersetExpr)
587591 case eval checkExpr of
588− Left err -> Just err
592+ Left err -> Left err
589593 Right resultRel -> if resultRel == relationTrue then
590− Nothing
594+ pure ()
591595 else
592− Just $ InclusionDependencyCheckError depName
596+ Left (InclusionDependencyCheckError depName)
593597
594598-- 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
595599-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation