@@ -244,8 +244,8 @@ setRelVar relVarName rel = do
244 potentialContext = currentContext { relationVariables = newRelVars }
244 potentialContext = currentContext { relationVariables = newRelVars }
246 case checkConstraints potentialContext of
246 case checkConstraints potentialContext of
247− Just err -> pure (Left err)
247+ Left err -> pure (Left err)
248− Nothing -> do
248+ Right _ -> do
249 putStateContext potentialContext
249 putStateContext potentialContext
250 return (Right ())
250 return (Right ())
@@ -295,7 +295,7 @@ evalDatabaseContextExpr (Assign relVarName expr) = do
295 if A.attributesEqual expectedAttributes foundAttributes then
295 if A.attributesEqual expectedAttributes foundAttributes then
296 setRelVar relVarName rel
296 setRelVar relVarName rel
298− pure (Left (RelVarAssignmentTypeMismatchError expectedAttributes foundAttributes))
298+ pure (Left (RelationTypeMismatchError expectedAttributes foundAttributes))
300evalDatabaseContextExpr (Insert relVarName relExpr) = do
300evalDatabaseContextExpr (Insert relVarName relExpr) = do
301 context <- getStateContext
301 context <- getStateContext
@@ -359,8 +359,8 @@ evalDatabaseContextExpr (AddInclusionDependency newDepName newDep) = do
360 let potentialContext = currContext { inclusionDependencies = newDeps }
360 let potentialContext = currContext { inclusionDependencies = newDeps }
361 case checkConstraints potentialContext of
361 case checkConstraints potentialContext of
362− Just err -> pure (Left err)
362+ Left err -> pure (Left err)
363− Nothing -> do
363+ Right _ -> do
364 putStateContext potentialContext
364 putStateContext potentialContext
365 return (Right ())
365 return (Right ())
@@ -574,22 +574,26 @@ updateTupleWithAtomExprs exprMap context tupIn = do
574 pure (updateTupleWithAtoms (M.fromList atomsAssoc) tupIn)
574 pure (updateTupleWithAtoms (M.fromList atomsAssoc) tupIn)
576--run verification on all constraints
576--run verification on all constraints
577−checkConstraints :: DatabaseContext -> Maybe RelationalError
577+checkConstraints :: DatabaseContext -> Either RelationalError ()
578−checkConstraints context = case failures of
578+checkConstraints context = do
579− [] -> Nothing
579+ mapM_ (uncurry checkIncDep) (M.toList deps)
580− l:_ -> Just l
580+ pure ()
582− failures = M.elems $ M.mapMaybeWithKey checkIncDep deps
583 deps = inclusionDependencies context
582 deps = inclusionDependencies context
584− eval expr = runReader (evalRelationalExpr expr) (RelationalExprStateElems context)
583+ eval expr = evalReader (evalRelationalExpr expr)
584+ evalReader f = runReader f (RelationalExprStateElems context)
585 checkIncDep depName (InclusionDependency subsetExpr supersetExpr) = do
585 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)))
586 let checkExpr = Equals supersetExpr (Union subsetExpr supersetExpr)
590 let checkExpr = Equals supersetExpr (Union subsetExpr supersetExpr)
587 case eval checkExpr of
591 case eval checkExpr of
588− Left err -> Just err
592+ Left err -> Left err
589 Right resultRel -> if resultRel == relationTrue then
593 Right resultRel -> if resultRel == relationTrue then
592− Just $ InclusionDependencyCheckError depName
596+ Left (InclusionDependencyCheckError depName)
594-- 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
598-- 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
595-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation
599-- furthermore, the type of a relational expression is the resultant header of the evaluated empty-tupled relation