Fix #1221, embedding when having a self join
This commit is contained in:
committed by
Steve Chávez
parent
1037313e77
commit
673aa25082
@@ -76,7 +76,7 @@ readRequest maxRows allRels proc apiRequest =
|
||||
buildReadRequest fieldTree =
|
||||
let rootDepth = 0
|
||||
rootNodeName = if action == ActionRead then rootTableName else sourceCTEName in
|
||||
foldr (treeEntry rootDepth) (Node (Select [] rootNodeName [] [] [] [] allRange, (rootNodeName, Nothing, Nothing, Nothing, rootDepth)) []) fieldTree
|
||||
foldr (treeEntry rootDepth) (Node (Select [] rootNodeName Nothing [] [] [] [] allRange, (rootNodeName, Nothing, Nothing, Nothing, rootDepth)) []) fieldTree
|
||||
where
|
||||
treeEntry :: Depth -> Tree SelectItem -> ReadRequest -> ReadRequest
|
||||
treeEntry depth (Node fld@((fn, _),_,alias,relationDetail) fldForest) (Node (q, i) rForest) =
|
||||
@@ -84,7 +84,7 @@ readRequest maxRows allRels proc apiRequest =
|
||||
case fldForest of
|
||||
[] -> Node (q {select=fld:select q}, i) rForest
|
||||
_ -> Node (q, i) $
|
||||
foldr (treeEntry nxtDepth) (Node (Select [] fn [] [] [] [] allRange, (fn, Nothing, alias, relationDetail, nxtDepth)) []) fldForest:rForest
|
||||
foldr (treeEntry nxtDepth) (Node (Select [] fn Nothing [] [] [] [] allRange, (fn, Nothing, alias, relationDetail, nxtDepth)) []) fldForest:rForest
|
||||
|
||||
relations :: [Relation]
|
||||
relations = case action of
|
||||
@@ -116,7 +116,7 @@ treeRestrictRange maxRows_ request = pure $ nodeRestrictRange maxRows_ `fmap` re
|
||||
augumentRequestWithJoin :: Schema -> [Relation] -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
augumentRequestWithJoin schema allRels request =
|
||||
addRelations schema allRels Nothing request
|
||||
>>= addJoinConditions schema
|
||||
>>= addJoinConditions schema Nothing
|
||||
|
||||
addRelations :: Schema -> [Relation] -> Maybe ReadRequest -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
addRelations schema allRelations parentNode (Node (query@Select{from=tbl}, (nodeName, _, alias, relationDetail, depth)) forest) =
|
||||
@@ -216,10 +216,11 @@ findRelation schema allRelations nodeTableName parentNodeTableName relationDetai
|
||||
)
|
||||
) allRelations
|
||||
|
||||
addJoinConditions :: Schema -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
addJoinConditions schema (Node node@(query, nodeProps@(_, relation, _, _, _)) forest) =
|
||||
-- previousAlias is only used for the case of self joins
|
||||
addJoinConditions :: Schema -> Maybe Alias -> ReadRequest -> Either ApiRequestError ReadRequest
|
||||
addJoinConditions schema previousAlias (Node node@(query@Select{from=tbl}, nodeProps@(_, relation, _, _, depth)) forest) =
|
||||
case relation of
|
||||
Just Relation{relType=Root} -> Node node <$> updatedForest -- this is the root node
|
||||
Just Relation{relType=Root} -> Node node <$> updatedForest -- this is the root node
|
||||
Just rel@Relation{relType=Parent} -> Node (augmentQuery rel, nodeProps) <$> updatedForest
|
||||
Just rel@Relation{relType=Child} -> Node (augmentQuery rel, nodeProps) <$> updatedForest
|
||||
Just rel@Relation{relType=Many, relLinkTable=(Just linkTable)} ->
|
||||
@@ -227,13 +228,21 @@ addJoinConditions schema (Node node@(query, nodeProps@(_, relation, _, _, _)) fo
|
||||
Node (rq{implicitJoins=tableName linkTable:implicitJoins rq}, nodeProps) <$> updatedForest
|
||||
_ -> Left UnknownRelation
|
||||
where
|
||||
updatedForest = mapM (addJoinConditions schema) forest
|
||||
augmentQuery rel = foldr addJoinCond query (getJoinConditions rel)
|
||||
addJoinCond :: JoinCondition -> ReadQuery -> ReadQuery
|
||||
addJoinCond jc rq@Select{joinConditions=jcs} = rq{joinConditions=jc:jcs}
|
||||
newAlias = case isSelfJoin <$> relation of
|
||||
Just True
|
||||
| depth /= 0 -> Just (tbl <> "_" <> show depth) -- root node doesn't get aliased
|
||||
| otherwise -> Nothing
|
||||
_ -> Nothing
|
||||
augmentQuery rel =
|
||||
foldr
|
||||
(\jc rq@Select{joinConditions=jcs} -> rq{joinConditions=jc:jcs})
|
||||
query{fromAlias=newAlias}
|
||||
(getJoinConditions previousAlias newAlias rel)
|
||||
updatedForest = mapM (addJoinConditions schema newAlias) forest
|
||||
|
||||
getJoinConditions :: Relation -> [JoinCondition]
|
||||
getJoinConditions (Relation Table{tableSchema=tSchema, tableName=tN} cols Table{tableName=ftN} fCols typ lt lc1 lc2) =
|
||||
-- previousAlias and newAlias are used in the case of self joins
|
||||
getJoinConditions :: Maybe Alias -> Maybe Alias -> Relation -> [JoinCondition]
|
||||
getJoinConditions previousAlias newAlias (Relation Table{tableSchema=tSchema, tableName=tN} cols Table{tableName=ftN} fCols typ lt lc1 lc2) =
|
||||
if | typ == Child || typ == Parent ->
|
||||
zipWith (toJoinCondition tN ftN) cols fCols
|
||||
| typ == Many ->
|
||||
@@ -243,8 +252,10 @@ getJoinConditions (Relation Table{tableSchema=tSchema, tableName=tN} cols Table{
|
||||
where
|
||||
toJoinCondition :: Text -> Text -> Column -> Column -> JoinCondition
|
||||
toJoinCondition tb ftb c fc =
|
||||
JoinCondition (QualifiedIdentifier tSchema tb, Nothing, colName c)
|
||||
(QualifiedIdentifier tSchema ftb, Nothing, colName fc)
|
||||
let qi1 = QualifiedIdentifier tSchema tb
|
||||
qi2 = QualifiedIdentifier tSchema ftb in
|
||||
JoinCondition (maybe qi1 (QualifiedIdentifier mempty) newAlias, colName c)
|
||||
(maybe qi2 (QualifiedIdentifier mempty) previousAlias, colName fc)
|
||||
|
||||
addFiltersOrdersRanges :: ApiRequest -> Either ApiRequestError (ReadRequest -> ReadRequest)
|
||||
addFiltersOrdersRanges apiRequest = foldr1 (liftA2 (.)) [
|
||||
|
||||
Reference in New Issue
Block a user