Skip to content

Commit

Permalink
override detected relationships
Browse files Browse the repository at this point in the history
  • Loading branch information
steve-chavez committed Aug 11, 2022
1 parent 84f67ce commit 3950b36
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 6 deletions.
26 changes: 21 additions & 5 deletions src/PostgREST/DbStructure.hs
Original file line number Diff line number Diff line change
Expand Up @@ -93,17 +93,33 @@ queryDbStructure schemas extraSearchPath prepared = do
cRels <- SQL.statement mempty $ allComputedRels prepared

let tabsWViewsPks = addViewPrimaryKeys tabs keyDeps
rels = relsToMap $ addO2MRels $ addM2MRels tabsWViewsPks $ addViewM2ORels keyDeps m2oRels
newRels = HM.union (HM.fromList $ map addKey cRels) rels -- TODO: currently replacing all the relationships for a single table
rels = addO2MRels $ addM2MRels tabsWViewsPks $ addViewM2ORels keyDeps m2oRels

return $ removeInternal schemas $ DbStructure {
dbTables = tabsWViewsPks
, dbRelationships = newRels
, dbRelationships = getOverrideRelationshipsMap rels cRels
, dbProcs = procs
}

-- | overrides detected relationships with the computed relationships and gets the RelationshipsMap
getOverrideRelationshipsMap :: [Relationship] -> [Relationship] -> RelationshipsMap
getOverrideRelationshipsMap rels cRels =
sort <$> deformedRelMap patchedRels
where
relsToMap = map sort . HM.fromListWith (++) . map addKey
addKey rel = ((relTable rel, qiSchema $ relForeignTable rel), [rel])
-- there can only be a single (table_type, func_name) pair in a function definition `test.function(table_type)`, so we use HM.fromList to disallow duplicates
computedRels = HM.fromList $ relMapKey <$> cRels
-- here we override the detected relationships with the user computed relationships, HM.union makes sure computedRels prevail
patchedRels = HM.union computedRels (relsMap rels)
relsMap = HM.fromListWith (++) . fmap relMapKey
relMapKey rel = case rel of
Relationship{relTable,relForeignTable} -> ((relTable, relForeignTable), [rel])
-- we use (relTable, relFunction) as key to override detected relationships with the function name
ComputedRelationShip{relTable,relFunction} -> ((relTable, relFunction), [rel])
-- Since a relationship is between a table and foreign table, the logical way to index/search is by their table/ftable QualifiedIdentifier
-- However, because we allow searching a relationship by the columns of the foreign key(using the "column as target" disambiguation) we lose the
-- ability to index by the foreign table name, so we deform the key. TODO remove once support for "column as target" is gone.
deformedRelMap = HM.fromListWith (++) . fmap addDeformedRelKey . HM.toList
addDeformedRelKey ((relT, relFT), rls) = ((relT, qiSchema relFT), rls)

-- | Remove db objects that belong to an internal schema(not exposed through the API) from the DbStructure.
removeInternal :: [Schema] -> DbStructure -> DbStructure
Expand Down
2 changes: 1 addition & 1 deletion src/PostgREST/Request/DbRequestBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ findRel schema allRels origin target hint =
O2M _ _ -> True
_ -> False
rels = filter (\case
ComputedRelationShip{relForeignTable} -> target == qiName relForeignTable
ComputedRelationShip{relFunction} -> target == qiName relFunction
Relationship{..} ->
-- In a self-relationship we have a single foreign key but two relationships with different cardinalities: M2O/O2M. For disambiguation, we use the convention of getting:
-- TODO: handle one-to-one and many-to-many self-relationships
Expand Down

0 comments on commit 3950b36

Please sign in to comment.