perf: RelationshipsMap with foreign schema as key

This commit is contained in:
steve-chavez
2022-05-09 21:31:19 -05:00
committed by Steve Chavez
parent d88b16e5ab
commit c60380b5fc
5 changed files with 49 additions and 41 deletions
+3 -3
View File
@@ -100,8 +100,8 @@ queryDbStructure schemas extraSearchPath prepared = do
, dbProcs = procs
}
where
relsToMap = map sort . M.fromListWith (++) . map ((\(x,y) -> (x, [y])) . addKey)
addKey rel = (relTable rel, rel)
relsToMap = map sort . M.fromListWith (++) . map ((\(x, fSch, y) -> ((x, fSch), [y])) . addKey)
addKey rel = (relTable rel, qiSchema $ relForeignTable rel, rel)
-- | Remove db objects that belong to an internal schema(not exposed through the API) from the DbStructure.
removeInternal :: [Schema] -> DbStructure -> DbStructure
@@ -109,7 +109,7 @@ removeInternal schemas dbStruct =
DbStructure {
dbTables = M.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas) $ dbTables dbStruct
, dbRelationships = filter (\r -> qiSchema (relForeignTable r) `elem` schemas && not (hasInternalJunction r)) <$>
M.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas ) (dbRelationships dbStruct)
M.filterWithKey (\(QualifiedIdentifier sch _, _) _ -> sch `elem` schemas ) (dbRelationships dbStruct)
, dbProcs = dbProcs dbStruct -- procs are only obtained from the exposed schemas, no need to filter them.
}
where
+3 -2
View File
@@ -13,7 +13,7 @@ import qualified Data.Aeson as JSON
import qualified Data.HashMap.Strict as M
import PostgREST.DbStructure.Identifiers (FieldName,
QualifiedIdentifier)
QualifiedIdentifier, Schema)
import Protolude
@@ -53,4 +53,5 @@ data Junction = Junction
isSelfReference :: Relationship -> Bool
isSelfReference r = relTable r == relForeignTable r
type RelationshipsMap = M.HashMap QualifiedIdentifier [Relationship]
-- | Key based on the source table and the foreign table schema
type RelationshipsMap = M.HashMap (QualifiedIdentifier, Schema) [Relationship]
+1 -1
View File
@@ -100,7 +100,7 @@ makeProperty tbl rels col = (colName col, Inline s)
rel = find (\case
Relationship{relCardinality=(M2O _ relColumns)} -> [colName col] == (fst <$> relColumns)
_ -> False
) $ fromMaybe mempty $ M.lookup (QualifiedIdentifier (tableSchema tbl) (tableName tbl)) rels
) $ fromMaybe mempty $ M.lookup (QualifiedIdentifier (tableSchema tbl) (tableName tbl), tableSchema tbl) rels
fCol = (headMay . (\r -> snd <$> relColumns (relCardinality r)) =<< rel)
fTbl = qiName . relForeignTable <$> rel
fTblCol = (,) <$> fTbl <*> fCol
+39 -32
View File
@@ -157,47 +157,54 @@ findRel schema allRels origin target hint =
rs -> Left $ AmbiguousRelBetween origin target rs
where
matchFKSingleCol hint_ card = case card of
O2M _ cols -> length cols == 1 && hint_ == head (fst <$> cols)
M2O _ cols -> length cols == 1 && hint_ == head (fst <$> cols)
_ -> False
O2M _ [(col, _)] -> hint_ == col
M2O _ [(col, _)] -> hint_ == col
_ -> False
matchFKRefSingleCol hint_ card = case card of
O2M _ cols -> length cols == 1 && hint_ == head (snd <$> cols)
M2O _ cols -> length cols == 1 && hint_ == head (snd <$> cols)
_ -> False
O2M _ [(_, fCol)] -> hint_ == fCol
M2O _ [(_, fCol)] -> hint_ == fCol
_ -> False
matchConstraint tar card = case card of
O2M cons _ -> tar == Just cons
M2O cons _ -> tar == Just cons
O2M cons _ -> tar == cons
M2O cons _ -> tar == cons
_ -> False
matchJunction hint_ card = case card of
M2M Junction{junTable} -> hint_ == Just (qiName junTable)
M2M Junction{junTable} -> hint_ == qiName junTable
_ -> False
rel = filter (
\Relationship{..} ->
-- foreign relationship need to be on the exposed schema
schema == qiSchema relForeignTable &&
(
-- /projects?select=clients(*)
target == qiName relForeignTable -- clients
||
-- /projects?select=projects_client_id_fkey(*)
matchConstraint (Just target) relCardinality -- projects_client_id_fkey
||
-- /projects?select=client_id(*)
matchFKSingleCol (Just target) relCardinality -- client_id
) && (
isNothing hint || -- hint is optional
case hint of
Nothing ->
-- /projects?select=clients(*)
target == qiName relForeignTable -- clients
||
-- /projects?select=projects_client_id_fkey(*)
matchConstraint target relCardinality -- projects_client_id_fkey
||
-- /projects?select=client_id(*)
matchFKSingleCol target relCardinality -- client_id
Just hnt ->
(
-- /projects?select=clients(*)
target == qiName relForeignTable -- clients
||
-- /projects?select=projects_client_id_fkey(*)
matchConstraint target relCardinality -- projects_client_id_fkey
||
-- /projects?select=client_id(*)
matchFKSingleCol target relCardinality -- client_id
) && (
-- /projects?select=clients!projects_client_id_fkey(*)
matchConstraint hnt relCardinality || -- projects_client_id_fkey
-- /projects?select=clients!projects_client_id_fkey(*)
matchConstraint hint relCardinality || -- projects_client_id_fkey
-- /projects?select=clients!client_id(*) or /projects?select=clients!id(*)
matchFKSingleCol hnt relCardinality || -- client_id
matchFKRefSingleCol hnt relCardinality || -- id
-- /projects?select=clients!client_id(*) or /projects?select=clients!id(*)
matchFKSingleCol hint relCardinality || -- client_id
matchFKRefSingleCol hint relCardinality || -- id
-- /users?select=tasks!users_tasks(*) many-to-many between users and tasks
matchJunction hint relCardinality -- users_tasks
)
) $ fromMaybe mempty $ M.lookup (QualifiedIdentifier schema origin) allRels
-- /users?select=tasks!users_tasks(*) many-to-many between users and tasks
matchJunction hnt relCardinality -- users_tasks
)
) $ fromMaybe mempty $ M.lookup (QualifiedIdentifier schema origin, schema) allRels
-- previousAlias is only used for the case of self joins
addJoinConditions :: Maybe Alias -> ReadRequest -> Either ApiRequestError ReadRequest
+3 -3
View File
@@ -26,7 +26,7 @@ spec =
it "accepts application/json" $
request methodGet "/"
[("Accept", "application/json")] "" `shouldRespondWith`
[json| {
"qiSchema":"test","qiName":"bars"
} |]
[json|
[{"qiSchema":"test","qiName":"authors_w_entities"},"test"]
|]
{ matchHeaders = [matchContentTypeJson] }