on master help sign in
initial, untested but functioning semijoin/antijoin implementation
commit5b585e7e23fa46555c16e978a09e943bb3c6b593 authorAgentM <agentm@themactionfaction.com> dateWed 6 Dec 2017, 23:25 (9 years ago) parent7905d57
9 files changed+153−73
src/bin/TutorialD/Interpreter/RelationalExpr.hs+26−10 src/lib/ProjectM36/Attribute.hs+10 src/lib/ProjectM36/AttributeNames.hs+1−29 src/lib/ProjectM36/Base.hs+11−7 src/lib/ProjectM36/Client.hs+1−1 src/lib/ProjectM36/Relation.hs+9−11 src/lib/ProjectM36/RelationalExpression.hs+67−9 src/lib/ProjectM36/StaticOptimizer.hs+4−3 src/lib/ProjectM36/TransGraphRelationalExpression.hs+24−3
src/bin/TutorialD/Interpreter/RelationalExpr.hs+26−10
@@ -18,12 +18,13 @@ instance RelationalMarkerExpr () where
1818 parseMarkerP = pure ()
1919
2020--used in projection
21−attributeListP :: Parser AttributeNames
22−attributeListP = do
23− but <- try (string "all but " <* spaceConsumer) <|> string ""
24− let constructor = if but == "" then AttributeNames else InvertedAttributeNames
25− attrs <- sepBy identifier comma
26− pure $ constructor (S.fromList attrs)
21+attributeListP :: RelationalMarkerExpr a => Parser (AttributeNamesBase a)
22+attributeListP =
23+ (reservedOp "all but" >>
24+ InvertedAttributeNames . S.fromList <$> sepBy identifier comma) <|>
25+ (reservedOp "all from" >>
26+ RelationalExprAttributeNames <$> relExprP) <|>
27+ (AttributeNames . S.fromList <$> sepBy identifier comma)
2728
2829makeRelationP :: RelationalMarkerExpr a => Parser (RelationalExprBase a)
2930makeRelationP = do
@@ -64,7 +65,7 @@ tupleAtomExprP = do
6465 atomExpr <- atomExprP
6566 pure (attributeName, atomExpr)
6667
67−projectP :: Parser (RelationalExprBase a -> RelationalExprBase a)
68+projectP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
6869projectP = do
6970 attrs <- braces attributeListP
7071 pure $ Project attrs
@@ -88,14 +89,14 @@ renameP = do
8889whereClauseP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
8990whereClauseP = reservedOp "where" *> (Restrict <$> restrictionPredicateP)
9091
91−groupClauseP :: Parser (AttributeNames, T.Text)
92+groupClauseP :: RelationalMarkerExpr a => Parser (AttributeNamesBase a, T.Text)
9293groupClauseP = do
9394 attrs <- braces attributeListP
9495 reservedOp "as"
9596 newAttrName <- identifier
9697 pure (attrs, newAttrName)
9798
98−groupP :: Parser (RelationalExprBase a -> RelationalExprBase a)
99+groupP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a)
99100groupP = do
100101 reservedOp "group"
101102 (groupAttrList, groupAttrName) <- parens groupClauseP
@@ -113,7 +114,20 @@ extendP = do
113114 reservedOp ":"
114115 tupleExpr <- braces extendTupleExpressionP
115116 return $ Extend tupleExpr
116−
117+
118+semijoinP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a -> RelationalExprBase a)
119+semijoinP = do
120+ reservedOp "semijoin" <|> reservedOp "matching"
121+ pure (\exprA exprB ->
122+ Project (RelationalExprAttributeNames exprA) (Join exprA exprB))
123+
124+antijoinP :: RelationalMarkerExpr a => Parser (RelationalExprBase a -> RelationalExprBase a -> RelationalExprBase a)
125+antijoinP = do
126+ reservedOp "not matching" <|> reservedOp "antijoin"
127+ pure (\exprA exprB ->
128+ Difference exprA (
129+ Project (RelationalExprAttributeNames exprA) (Join exprA exprB)))
130+
117131relOperators :: RelationalMarkerExpr a => [[Operator Parser (RelationalExprBase a)]]
118132relOperators = [
119133 [Postfix projectP],
@@ -122,6 +136,8 @@ relOperators = [
122136 [Postfix groupP],
123137 [Postfix ungroupP],
124138 [InfixL (reservedOp "join" >> return Join)],
139+ [InfixL semijoinP],
140+ [InfixL antijoinP],
125141 [InfixL (reservedOp "union" >> return Union)],
126142 [InfixL (reservedOp "minus" >> return Difference)],
127143 [InfixN (reservedOp "=" >> return Equals)],
src/lib/ProjectM36/Attribute.hs+10
@@ -71,6 +71,16 @@ attributeForName attrName attrs = case V.find (\attr -> attributeName attr == at
7171 Nothing -> Left (NoSuchAttributeNamesError (S.singleton attrName))
7272 Just attr -> Right attr
7373
74+--similar to attributesForNames, but returns error if some names are missing
75+projectionAttributesForNames :: S.Set AttributeName -> Attributes -> Either RelationalError Attributes
76+projectionAttributesForNames names attrsIn =
77+ if not (S.null missingNames) then
78+ Left (NoSuchAttributeNamesError missingNames)
79+ else
80+ Right (attributesForNames names attrsIn)
81+ where
82+ missingNames = attributeNamesNotContained names (S.fromList (V.toList (attributeNames attrsIn)))
83+
7484attributesForNames :: S.Set AttributeName -> Attributes -> Attributes
7585attributesForNames attrNameSet = V.filter filt
7686 where
src/lib/ProjectM36/AttributeNames.hs+1−29
@@ -1,38 +1,10 @@
11module ProjectM36.AttributeNames where
2−import qualified ProjectM36.Attribute as A
32import ProjectM36.Base
4−import ProjectM36.Error
53import qualified Data.Set as S
6−--AttributeNames is a data structure which can represent inverted projection attributes
4+--AttributeNames is a data structure which can represent inverted projection attributes and attribute names derived from relational expressions
75
86empty :: AttributeNames
97empty = AttributeNames S.empty
108
119all :: AttributeNames
1210all = InvertedAttributeNames S.empty
13−
14−--check that the attribute names are actually in the attributes
15−projectionAttributesForAttributeNames :: Attributes -> AttributeNames -> Either RelationalError Attributes
16−projectionAttributesForAttributeNames attrs (AttributeNames attrNameSet) = do
17− let nonExistentAttributeNames = A.attributeNamesNotContained attrNameSet (A.attributeNameSet attrs)
18− if not $ S.null nonExistentAttributeNames then
19− Left $ AttributeNamesMismatchError nonExistentAttributeNames
20− else
21− return $ A.attributesForNames attrNameSet attrs
22−projectionAttributesForAttributeNames attrs (InvertedAttributeNames unselectedAttrNameSet) = do
23− let nonExistentAttributeNames = A.attributeNamesNotContained unselectedAttrNameSet (A.attributeNameSet attrs)
24− if not $ S.null nonExistentAttributeNames then
25− Left $ AttributeNamesMismatchError nonExistentAttributeNames
26− else
27− return $ A.attributesForNames (A.nonMatchingAttributeNameSet unselectedAttrNameSet (A.attributeNameSet attrs)) attrs
28−projectionAttributesForAttributeNames attrs (UnionAttributeNames namesA namesB) = do
29− attrsA <- projectionAttributesForAttributeNames attrs namesA
30− attrsB <- projectionAttributesForAttributeNames attrs namesB
31− pure (A.union attrsA attrsB)
32−projectionAttributesForAttributeNames attrs (IntersectAttributeNames namesA namesB) = A.intersection <$> projectionAttributesForAttributeNames attrs namesA <*> projectionAttributesForAttributeNames attrs namesB
33−
34−invertAttributeNames :: AttributeNames -> AttributeNames
35−invertAttributeNames (AttributeNames names) = InvertedAttributeNames names
36−invertAttributeNames (InvertedAttributeNames names) = AttributeNames names
37−invertAttributeNames (UnionAttributeNames namesA namesB) = IntersectAttributeNames (invertAttributeNames namesA) (invertAttributeNames namesB)
38−invertAttributeNames (IntersectAttributeNames namesA namesB) = UnionAttributeNames (invertAttributeNames namesA) (invertAttributeNames namesB)
src/lib/ProjectM36/Base.hs+11−7
@@ -197,7 +197,7 @@ data RelationalExprBase a =
197197 --- | Reference a relation variable by its name.
198198 RelationVariable RelVarName a |
199199 --- | Create a projection over attribute names. (Note that the 'AttributeNames' structure allows for the names to be inverted.)
200− Project AttributeNames (RelationalExprBase a) |
200+ Project (AttributeNamesBase a) (RelationalExprBase a) |
201201 --- | Create a union of two relational expressions. The expressions should have identical attributes.
202202 Union (RelationalExprBase a) (RelationalExprBase a) |
203203 --- | Create a join of two relational expressions. The join occurs on attributes which are identical. If the expressions have no overlapping attributes, the join becomes a cross-product of both tuple sets.
@@ -207,7 +207,7 @@ data RelationalExprBase a =
207207 --- | Return a relation containing all tuples of the first argument which do not appear in the second argument (minus).
208208 Difference (RelationalExprBase a) (RelationalExprBase a) |
209209 --- | Create a sub-relation composed of the first argument's attributes which will become an attribute of the result expression. The unreferenced attributes are not altered in the result but duplicate tuples in the projection of the expression minus the attribute names are compressed into one. For more information, <https://github.com/agentm/project-m36/blob/master/docs/introduction_to_the_relational_algebra.markdown#group read the relational algebra tutorial.>
210− Group AttributeNames AttributeName (RelationalExprBase a) |
210+ Group (AttributeNamesBase a) AttributeName (RelationalExprBase a) |
211211 --- | Create an expression to unwrap a sub-relation contained within at an attribute's name. Note that this is not always an inverse of a group operation.
212212 Ungroup AttributeName (RelationalExprBase a) |
213213 --- | Filter the tuples of the relational expression to only retain the tuples which evaluate against the restriction predicate to true.
@@ -461,11 +461,15 @@ instance Show AtomFunction where
461461 showArgTypes = L.intercalate "->" (map show (atomFuncType aFunc))
462462
463463-- | The 'AttributeNames' structure represents a set of attribute names or the same set of names but inverted in the context of a relational expression. For example, if a relational expression has attributes named "a", "b", and "c", the 'InvertedAttributeNames' of ("a","c") is ("b").
464−data AttributeNames = AttributeNames (S.Set AttributeName) |
465− InvertedAttributeNames (S.Set AttributeName) |
466− UnionAttributeNames AttributeNames AttributeNames |
467− IntersectAttributeNames AttributeNames AttributeNames
468− deriving (Eq, Show, Generic, Binary, NFData)
464+data AttributeNamesBase a = AttributeNames (S.Set AttributeName) |
465+ InvertedAttributeNames (S.Set AttributeName) |
466+ UnionAttributeNames (AttributeNamesBase a) (AttributeNamesBase a) |
467+ IntersectAttributeNames (AttributeNamesBase a) (AttributeNamesBase a) |
468+ RelationalExprAttributeNames (RelationalExprBase a) -- use attribute names from the relational expression's type
469+ deriving (Eq, Show, Generic, NFData)
470+
471+type AttributeNames = AttributeNamesBase ()
472+instance Binary AttributeNames
469473
470474-- | The persistence strategy is a global database option which represents how to persist the database in the filesystem, if at all.
471475data PersistenceStrategy = NoPersistence | -- ^ no filesystem persistence/memory-only database
src/lib/ProjectM36/Client.hs+1−1
@@ -79,7 +79,7 @@ module ProjectM36.Client
7979 TypeConstructor(..),
8080 TypeConstructorDef(..),
8181 DataConstructorDef(..),
82− AttributeNames(..),
82+ AttributeNamesBase(..),
8383 RelVarName,
8484 IncDepName,
8585 InclusionDependency(..),
src/lib/ProjectM36/Relation.hs+9−11
@@ -9,7 +9,6 @@ import ProjectM36.AtomType
99import ProjectM36.Base
1010import ProjectM36.Tuple
1111import qualified ProjectM36.Attribute as A
12−import qualified ProjectM36.AttributeNames as AS
1312import ProjectM36.TupleSet
1413import ProjectM36.Error
1514import ProjectM36.MiscUtils
@@ -94,11 +93,10 @@ union (Relation attrs1 tupSet1) (Relation attrs2 tupSet2) =
9493 where
9594 newtuples = RelationTupleSet $ HS.toList . HS.fromList $ asList tupSet1 ++ map (reorderTuple attrs1) (asList tupSet2)
9695
97−project :: AttributeNames -> Relation -> Either RelationalError Relation
98−project projectionAttrNames rel =
99− case AS.projectionAttributesForAttributeNames (attributes rel) projectionAttrNames of
100− Left err -> Left err
101− Right newAttrs -> relFold (folder newAttrs) (Right $ Relation newAttrs emptyTupleSet) rel
96+project :: S.Set AttributeName -> Relation -> Either RelationalError Relation
97+project attrNames rel = do
98+ newAttrs <- A.projectionAttributesForNames attrNames (attributes rel)
99+ relFold (folder newAttrs) (Right $ Relation newAttrs emptyTupleSet) rel
102100 where
103101 folder newAttrs tupleToProject acc = case acc of
104102 Left err -> Left err
@@ -149,11 +147,11 @@ group groupAttrNames newAttrName rel@(Relation oldAttrs tupleSet) = do
149147-}
150148
151149--algorithm: self-join with image relation
152−group :: AttributeNames -> AttributeName -> Relation -> Either RelationalError Relation
150+group :: S.Set AttributeName -> AttributeName -> Relation -> Either RelationalError Relation
153151group groupAttrNames newAttrName rel = do
154− let nonGroupAttrNames = AS.invertAttributeNames groupAttrNames
155− nonGroupProjectionAttributes <- AS.projectionAttributesForAttributeNames (attributes rel) nonGroupAttrNames
156− groupProjectionAttributes <- AS.projectionAttributesForAttributeNames (attributes rel) groupAttrNames
152+ let nonGroupAttrNames = A.attributeNamesNotContained groupAttrNames (S.fromList (V.toList (A.attributeNames (attributes rel))))
153+ nonGroupProjectionAttributes <- A.projectionAttributesForNames nonGroupAttrNames (attributes rel)
154+ groupProjectionAttributes <- A.projectionAttributesForNames groupAttrNames (attributes rel)
157155 let groupAttr = Attribute newAttrName (RelationAtomType groupProjectionAttributes)
158156 matchingRelTuple tupIn = case imageRelationFor tupIn rel of
159157 Right rel2 -> RelationTuple (V.singleton groupAttr) (V.singleton (RelationAtom rel2))
@@ -274,7 +272,7 @@ toList rel = do
274272imageRelationFor :: RelationTuple -> Relation -> Either RelationalError Relation
275273imageRelationFor matchTuple rel = do
276274 restricted <- restrictEq matchTuple rel --restrict across matching tuples
277− let projectionAttrNames = AttributeNames $ A.nonMatchingAttributeNameSet (attributeNames rel) (tupleAttributeNameSet matchTuple)
275+ let projectionAttrNames = A.nonMatchingAttributeNameSet (attributeNames rel) (tupleAttributeNameSet matchTuple)
278276 project projectionAttrNames restricted --project across attributes not in rel
279277
280278--returns a relation-valued attribute image relation for each tuple in rel1
src/lib/ProjectM36/RelationalExpression.hs+67−9
@@ -14,6 +14,7 @@ import ProjectM36.DatabaseContextFunction
1414import qualified ProjectM36.Attribute as A
1515import qualified Data.Map as M
1616import qualified Data.HashSet as HS
17+import qualified Data.Set as S
1718import Control.Monad.State hiding (join)
1819import Control.Exception
1920import Data.Maybe
@@ -113,10 +114,14 @@ evalRelationalExpr (RelationVariable name _) = do
113114 Nothing -> Left $ RelVarNotDefinedError name
114115
115116evalRelationalExpr (Project attrNames expr) = do
116− rel <- evalRelationalExpr expr
117− case rel of
118− Right rel2 -> return $ project attrNames rel2
119− Left err -> return $ Left err
117+ eAttrNameSet <- evalAttributeNames attrNames expr
118+ case eAttrNameSet of
119+ Left err -> pure (Left err)
120+ Right attrNameSet -> do
121+ rel <- evalRelationalExpr expr
122+ case rel of
123+ Right rel2 -> pure $ project attrNameSet rel2
124+ Left err -> pure $ Left err
120125
121126evalRelationalExpr (Union exprA exprB) = do
122127 relA <- evalRelationalExpr exprA
@@ -173,11 +178,15 @@ evalRelationalExpr (Rename oldAttrName newAttrName relExpr) = do
173178 Right rel -> return $ rename oldAttrName newAttrName rel
174179 Left err -> return $ Left err
175180
176−evalRelationalExpr (Group oldAttrNameSet newAttrName relExpr) = do
177− evald <- evalRelationalExpr relExpr
178− case evald of
179− Right rel -> return $ group oldAttrNameSet newAttrName rel
180− Left err -> return $ Left err
181+evalRelationalExpr (Group oldAttrNames newAttrName relExpr) = do
182+ eOldAttrNameSet <- evalAttributeNames oldAttrNames relExpr
183+ case eOldAttrNameSet of
184+ Left err -> pure (Left err)
185+ Right oldAttrNameSet -> do
186+ evald <- evalRelationalExpr relExpr
187+ case evald of
188+ Right rel -> return $ group oldAttrNameSet newAttrName rel
189+ Left err -> return $ Left err
181190
182191evalRelationalExpr (Ungroup attrName relExpr) = do
183192 evald <- evalRelationalExpr relExpr
@@ -871,3 +880,52 @@ evalTupleExpr attrs (TupleExpr tupMap) = do
871880 _ <- either throwE pure (validateTuple tup' tConss)
872881 pure tup'
873882
883+evalAttributeNames :: AttributeNames -> RelationalExpr -> RelationalExprState (Either RelationalError (S.Set AttributeName))
884+evalAttributeNames attrNames expr = do
885+ eExprType <- typeForRelationalExpr expr
886+ case eExprType of
887+ Left err -> pure (Left err)
888+ Right exprTyp -> do
889+ let typeNameSet = S.fromList (V.toList (A.attributeNames (attributes exprTyp)))
890+ case attrNames of
891+ AttributeNames names ->
892+ case A.projectionAttributesForNames names (attributes exprTyp) of
893+ Left err -> pure (Left err)
894+ Right attrs -> pure (Right (S.fromList (V.toList (A.attributeNames attrs))))
895+
896+ InvertedAttributeNames names -> do
897+ let nonExistentAttributeNames = A.attributeNamesNotContained names typeNameSet
898+ if not (S.null nonExistentAttributeNames) then
899+ pure (Left (AttributeNamesMismatchError nonExistentAttributeNames))
900+ else
901+ pure (Right (A.nonMatchingAttributeNameSet names typeNameSet))
902+
903+ UnionAttributeNames namesA namesB -> do
904+ eNameSetA <- evalAttributeNames namesA expr
905+ case eNameSetA of
906+ Left err -> pure (Left err)
907+ Right nameSetA -> do
908+ eNameSetB <- evalAttributeNames namesB expr
909+ case eNameSetB of
910+ Left err -> pure (Left err)
911+ Right nameSetB ->
912+ pure (Right (S.union nameSetA nameSetB))
913+
914+ IntersectAttributeNames namesA namesB -> do
915+ eNameSetA <- evalAttributeNames namesA expr
916+ case eNameSetA of
917+ Left err -> pure (Left err)
918+ Right nameSetA -> do
919+ eNameSetB <- evalAttributeNames namesB expr
920+ case eNameSetB of
921+ Left err -> pure (Left err)
922+ Right nameSetB ->
923+ pure (Right (S.intersection nameSetA nameSetB))
924+
925+ RelationalExprAttributeNames attrExpr -> do
926+ eAttrExprType <- typeForRelationalExpr attrExpr
927+ case eAttrExprType of
928+ Left err -> pure (Left err)
929+ Right attrExprType -> pure (Right (A.attributeNameSet (attributes attrExprType)))
930+
931+
src/lib/ProjectM36/StaticOptimizer.hs+4−3
@@ -320,6 +320,7 @@ isStaticAtomExpr RelationAtomExpr{} = False
320320--if the projection of a join only uses the attributes from one of the expressions and there is a foreign key relationship between the expressions, we know that the join is inconsequential and can be removed
321321applyStaticJoinElimination :: RelationalExpr -> RelationalExprState (Either RelationalError RelationalExpr)
322322applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
323+ relState <- ask
323324 eProjType <- typeForRelationalExpr expr
324325 eTypeA <- typeForRelationalExpr exprA
325326 eTypeB <- typeForRelationalExpr exprB
@@ -349,13 +350,13 @@ applyStaticJoinElimination expr@(Project attrNameSet (Join exprA exprB)) = do
349350 let fkConstraint = foldM isFkConstraint False incDeps
350351 --search for matching fk constraint
351352 isFkConstraint acc (InclusionDependency (Project subattrNames subrv) (Project _ superrv)) =
352− case AS.projectionAttributesForAttributeNames (attributes projType) subattrNames of
353+ case runReader (evalAttributeNames subattrNames subrv) relState of
353354 Left _ -> pure acc
354− Right subAttrs ->
355+ Right subAttrNameSet ->
355356 pure (acc || (joinedExpr == subrv &&
356357 unjoinedExpr == superrv &&
357358 -- the fk attribute is one of the projection attributes
358− A.attributesContained subAttrs (attributes joinedType)
359+ A.attributeNamesContained subAttrNameSet (A.attributeNameSet (attributes joinedType))
359360 ))
360361 isFkConstraint acc _ = pure acc
361362 case fkConstraint of
src/lib/ProjectM36/TransGraphRelationalExpression.hs+24−3
@@ -18,6 +18,10 @@ type TransGraphRelationalExpr = RelationalExprBase TransactionIdLookup
1818
1919instance Binary TransGraphRelationalExpr
2020
21+type TransGraphAttributeNames = AttributeNamesBase TransactionIdLookup
22+
23+instance Binary TransGraphAttributeNames
24+
2125type TransGraphExtendTupleExpr = ExtendTupleExprBase TransactionIdLookup
2226
2327instance Binary TransGraphExtendTupleExpr
@@ -51,13 +55,14 @@ evalTransGraphRelationalExpr (RelationVariable rvname transLookup) graph = do
5155 trans <- lookupTransaction graph transLookup
5256 rel <- runReader (evalRelationalExpr (RelationVariable rvname ())) (RelationalExprStateElems (concreteDatabaseContext trans))
5357 pure (ExistingRelation rel)
54−evalTransGraphRelationalExpr (Project attrNames expr) graph = do
58+evalTransGraphRelationalExpr (Project transAttrNames expr) graph = do
5559 expr' <- evalTransGraphRelationalExpr expr graph
60+ attrNames <- evalTransAttributeNames transAttrNames graph
5661 pure (Project attrNames expr')
5762evalTransGraphRelationalExpr (Union exprA exprB) graph = do
5863 exprA' <- evalTransGraphRelationalExpr exprA graph
5964 exprB' <- evalTransGraphRelationalExpr exprB graph
60− pure (Union exprA' exprB')
65+ pure (Union exprA' exprB')
6166evalTransGraphRelationalExpr (Join exprA exprB) graph = do
6267 exprA' <- evalTransGraphRelationalExpr exprA graph
6368 exprB' <- evalTransGraphRelationalExpr exprB graph
@@ -69,8 +74,9 @@ evalTransGraphRelationalExpr (Difference exprA exprB) graph = do
6974 exprA' <- evalTransGraphRelationalExpr exprA graph
7075 exprB' <- evalTransGraphRelationalExpr exprB graph
7176 pure (Difference exprA' exprB')
72−evalTransGraphRelationalExpr (Group attrNames attrName expr) graph = do
77+evalTransGraphRelationalExpr (Group transAttrNames attrName expr) graph = do
7378 expr' <- evalTransGraphRelationalExpr expr graph
79+ attrNames <- evalTransAttributeNames transAttrNames graph
7480 pure (Group attrNames attrName expr')
7581evalTransGraphRelationalExpr (Ungroup attrName expr) graph = do
7682 expr' <- evalTransGraphRelationalExpr expr graph
@@ -152,3 +158,18 @@ evalTransGraphAttributeExpr graph (AttributeAndTypeNameExpr attrName tCons tLook
152158 aType <- atomTypeForTypeConstructor tCons (typeConstructorMapping (concreteDatabaseContext trans)) M.empty
153159 pure (NakedAttributeExpr (Attribute attrName aType))
154160evalTransGraphAttributeExpr _ (NakedAttributeExpr attr) = pure (NakedAttributeExpr attr)
161+
162+evalTransAttributeNames :: TransGraphAttributeNames -> TransactionGraph -> Either RelationalError AttributeNames
163+evalTransAttributeNames (AttributeNames names) _ = Right (AttributeNames names)
164+evalTransAttributeNames (InvertedAttributeNames names) _ = Right (InvertedAttributeNames names)
165+evalTransAttributeNames (UnionAttributeNames namesA namesB) graph = do
166+ nA <- evalTransAttributeNames namesA graph
167+ nB <- evalTransAttributeNames namesB graph
168+ Right (UnionAttributeNames nA nB)
169+evalTransAttributeNames (IntersectAttributeNames namesA namesB) graph = do
170+ nA <- evalTransAttributeNames namesA graph
171+ nB <- evalTransAttributeNames namesB graph
172+ Right (IntersectAttributeNames nA nB)
173+evalTransAttributeNames (RelationalExprAttributeNames expr) graph = do
174+ evaldExpr <- evalTransGraphRelationalExpr expr graph
175+ Right (RelationalExprAttributeNames evaldExpr)