refactor: remove Table from Relationship

Just having the QualifiedIdentifier gets us closer to having
Relationship as a Table attribute since it avoids a cyclic dependency

* remove unnecessary findTable
* modify RootSpec test
This commit is contained in:
steve-chavez
2022-04-18 15:48:03 -05:00
committed by Steve Chavez
parent cdcc175abf
commit 7f1507b9fb
9 changed files with 54 additions and 65 deletions
+2 -3
View File
@@ -63,8 +63,7 @@ import PostgREST.Config (AppConfig (..),
import PostgREST.Config.PgVersion (PgVersion (..)) import PostgREST.Config.PgVersion (PgVersion (..))
import PostgREST.ContentType (ContentType (..)) import PostgREST.ContentType (ContentType (..))
import PostgREST.DbStructure (DbStructure (..), import PostgREST.DbStructure (DbStructure (..),
findIfView, findTable, findIfView, tablePKCols)
tablePKCols)
import PostgREST.DbStructure.Identifiers (FieldName, import PostgREST.DbStructure.Identifiers (FieldName,
QualifiedIdentifier (..), QualifiedIdentifier (..),
Schema) Schema)
@@ -417,7 +416,7 @@ handleDelete identifier context@(RequestContext _ ctxDbStructure ApiRequest{..}
handleInfo :: Monad m => QualifiedIdentifier -> RequestContext -> Handler m Wai.Response handleInfo :: Monad m => QualifiedIdentifier -> RequestContext -> Handler m Wai.Response
handleInfo identifier RequestContext{..} = handleInfo identifier RequestContext{..} =
case findTable identifier $ dbTables ctxDbStructure of case M.lookup identifier $ dbTables ctxDbStructure of
Just table -> Just table ->
return $ Wai.responseLBS HTTP.status200 [allOrigins, allowH table] mempty return $ Wai.responseLBS HTTP.status200 [allOrigins, allowH table] mempty
Nothing -> Nothing ->
+20 -25
View File
@@ -24,7 +24,6 @@ module PostgREST.DbStructure
, accessibleTables , accessibleTables
, accessibleProcs , accessibleProcs
, findIfView , findIfView
, findTable
, schemaDescription , schemaDescription
, tableCols , tableCols
, tablePKCols , tablePKCols
@@ -57,7 +56,8 @@ import PostgREST.DbStructure.Relationship (Cardinality (..),
Junction (..), Junction (..),
PrimaryKey (..), PrimaryKey (..),
Relationship (..)) Relationship (..))
import PostgREST.DbStructure.Table (Column (..), Table (..), TablesMap) import PostgREST.DbStructure.Table (Column (..), Table (..),
TablesMap)
import Protolude import Protolude
import Protolude.Unsafe (unsafeHead) import Protolude.Unsafe (unsafeHead)
@@ -80,11 +80,8 @@ tableCols dbs tSchema tName = filter (\Column{colTable=Table{tableSchema=s, tabl
tablePKCols :: DbStructure -> Schema -> TableName -> [Text] tablePKCols :: DbStructure -> Schema -> TableName -> [Text]
tablePKCols dbs tSchema tName = pkName <$> filter (\pk -> tSchema == (tableSchema . pkTable) pk && tName == (tableName . pkTable) pk) (dbPrimaryKeys dbs) tablePKCols dbs tSchema tName = pkName <$> filter (\pk -> tSchema == (tableSchema . pkTable) pk && tName == (tableName . pkTable) pk) (dbPrimaryKeys dbs)
findTable :: QualifiedIdentifier -> TablesMap -> Maybe Table
findTable identifier tbls = M.lookup identifier tbls
findIfView :: QualifiedIdentifier -> TablesMap -> Bool findIfView :: QualifiedIdentifier -> TablesMap -> Bool
findIfView identifier tbls = maybe False tableIsView $ findTable identifier tbls findIfView identifier tbls = maybe False tableIsView $ M.lookup identifier tbls
-- | The source table column a view column refers to -- | The source table column a view column refers to
type SourceColumn = (Column, ViewColumn) type SourceColumn = (Column, ViewColumn)
@@ -100,7 +97,7 @@ queryDbStructure schemas extraSearchPath prepared = do
tabs <- SQL.statement mempty $ allTables pgVer prepared tabs <- SQL.statement mempty $ allTables pgVer prepared
cols <- SQL.statement schemas $ allColumns tabs prepared cols <- SQL.statement schemas $ allColumns tabs prepared
srcCols <- SQL.statement (schemas, extraSearchPath) $ pfkSourceColumns cols prepared srcCols <- SQL.statement (schemas, extraSearchPath) $ pfkSourceColumns cols prepared
m2oRels <- SQL.statement mempty $ allM2ORels tabs cols prepared m2oRels <- SQL.statement mempty $ allM2ORels cols prepared
keys <- SQL.statement mempty $ allPrimaryKeys tabs prepared keys <- SQL.statement mempty $ allPrimaryKeys tabs prepared
procs <- SQL.statement schemas $ allProcs pgVer prepared procs <- SQL.statement schemas $ allProcs pgVer prepared
@@ -121,15 +118,15 @@ removeInternal schemas dbStruct =
DbStructure { DbStructure {
dbTables = M.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas) $ dbTables dbStruct dbTables = M.filterWithKey (\(QualifiedIdentifier sch _) _ -> sch `elem` schemas) $ dbTables dbStruct
, dbColumns = filter (\x -> tableSchema (colTable x) `elem` schemas) (dbColumns dbStruct) , dbColumns = filter (\x -> tableSchema (colTable x) `elem` schemas) (dbColumns dbStruct)
, dbRelationships = filter (\x -> tableSchema (relTable x) `elem` schemas && , dbRelationships = filter (\x -> qiSchema (relTable x) `elem` schemas &&
tableSchema (relForeignTable x) `elem` schemas && qiSchema (relForeignTable x) `elem` schemas &&
not (hasInternalJunction x)) $ dbRelationships dbStruct not (hasInternalJunction x)) $ dbRelationships dbStruct
, dbPrimaryKeys = filter (\x -> tableSchema (pkTable x) `elem` schemas) $ dbPrimaryKeys dbStruct , dbPrimaryKeys = filter (\x -> tableSchema (pkTable x) `elem` schemas) $ dbPrimaryKeys dbStruct
, dbProcs = dbProcs dbStruct -- procs are only obtained from the exposed schemas, no need to filter them. , dbProcs = dbProcs dbStruct -- procs are only obtained from the exposed schemas, no need to filter them.
} }
where where
hasInternalJunction rel = case relCardinality rel of hasInternalJunction rel = case relCardinality rel of
M2M Junction{junTable} -> tableSchema junTable `notElem` schemas M2M Junction{junTable} -> qiSchema junTable `notElem` schemas
_ -> False _ -> False
decodeTables :: HD.Result TablesMap decodeTables :: HD.Result TablesMap
@@ -160,9 +157,9 @@ decodeColumns tables =
<*> nullableColumn HD.text <*> nullableColumn HD.text
<*> nullableColumn HD.text <*> nullableColumn HD.text
decodeRels :: TablesMap -> [Column] -> HD.Result [Relationship] decodeRels :: [Column] -> HD.Result [Relationship]
decodeRels tables cols = decodeRels cols =
mapMaybe (relFromRow tables cols) <$> HD.rowList relRow mapMaybe (relFromRow cols) <$> HD.rowList relRow
where where
relRow = (,,,,,,) relRow = (,,,,,,)
<$> column HD.text <$> column HD.text
@@ -378,8 +375,8 @@ addViewM2ORels allSrcCols = concatMap (\rel@Relationship{..} -> rel :
filter (\(c, _) -> c `elem` relCols) allSrcCols filter (\(c, _) -> c `elem` relCols) allSrcCols
relSrcCols = srcColsGroupedByView relColumns relSrcCols = srcColsGroupedByView relColumns
relFSrcCols = srcColsGroupedByView relForeignColumns relFSrcCols = srcColsGroupedByView relForeignColumns
getView :: [SourceColumn] -> Table getView :: [SourceColumn] -> QualifiedIdentifier
getView = colTable . snd . unsafeHead getView = (\t -> QualifiedIdentifier (tableSchema t) (tableName t)) . colTable . snd . unsafeHead
srcCols `allSrcColsOf` cols = S.fromList (fst <$> srcCols) == S.fromList cols srcCols `allSrcColsOf` cols = S.fromList (fst <$> srcCols) == S.fromList cols
-- Relationship is dependent on the order of relColumns and relFColumns to get the join conditions right in the generated query. -- Relationship is dependent on the order of relColumns and relFColumns to get the join conditions right in the generated query.
-- So we need to change the order of the SourceColumns to match the relColumns -- So we need to change the order of the SourceColumns to match the relColumns
@@ -612,13 +609,13 @@ columnFromRow :: TablesMap ->
columnFromRow tabs (s, t, n, desc, nul, typ, l, d, e) = buildColumn <$> table columnFromRow tabs (s, t, n, desc, nul, typ, l, d, e) = buildColumn <$> table
where where
buildColumn tbl = Column tbl n desc nul typ l d (parseEnum e) buildColumn tbl = Column tbl n desc nul typ l d (parseEnum e)
table = findTable (QualifiedIdentifier s t) tabs table = M.lookup (QualifiedIdentifier s t) tabs
parseEnum :: Maybe Text -> [Text] parseEnum :: Maybe Text -> [Text]
parseEnum = maybe [] (split (==',')) parseEnum = maybe [] (split (==','))
allM2ORels :: TablesMap -> [Column] -> Bool -> SQL.Statement () [Relationship] allM2ORels :: [Column] -> Bool -> SQL.Statement () [Relationship]
allM2ORels tabs cols = allM2ORels allCols =
SQL.Statement sql HE.noParams (decodeRels tabs cols) SQL.Statement sql HE.noParams (decodeRels allCols)
where where
sql = [q| sql = [q|
SELECT ns1.nspname AS table_schema, SELECT ns1.nspname AS table_schema,
@@ -643,13 +640,11 @@ allM2ORels tabs cols =
WHERE confrelid != 0 WHERE confrelid != 0
ORDER BY (conrelid, column_info.nums) |] ORDER BY (conrelid, column_info.nums) |]
relFromRow :: TablesMap -> [Column] -> (Text, Text, Text, [Text], Text, Text, [Text]) -> Maybe Relationship relFromRow :: [Column] -> (Text, Text, Text, [Text], Text, Text, [Text]) -> Maybe Relationship
relFromRow allTabs allCols (rs, rt, cn, rcs, frs, frt, frcs) = relFromRow allCols (rs, rt, cn, rcs, frs, frt, frcs) =
Relationship <$> table <*> cols <*> tableF <*> colsF <*> pure (M2O cn) Relationship (QualifiedIdentifier rs rt) <$> cols <*> pure (QualifiedIdentifier frs frt) <*> colsF <*> pure (M2O cn)
where where
findCol s t c = find (\col -> tableSchema (colTable col) == s && tableName (colTable col) == t && colName col == c) allCols findCol s t c = find (\col -> tableSchema (colTable col) == s && tableName (colTable col) == t && colName col == c) allCols
table = findTable (QualifiedIdentifier rs rt) allTabs
tableF = findTable (QualifiedIdentifier frs frt) allTabs
cols = mapM (findCol rs rt) rcs cols = mapM (findCol rs rt) rcs
colsF = mapM (findCol frs frt) frcs colsF = mapM (findCol frs frt) frcs
@@ -731,7 +726,7 @@ allPrimaryKeys tabs =
pkFromRow :: TablesMap -> (Schema, Text, Text) -> Maybe PrimaryKey pkFromRow :: TablesMap -> (Schema, Text, Text) -> Maybe PrimaryKey
pkFromRow tabs (s, t, n) = PrimaryKey <$> table <*> pure n pkFromRow tabs (s, t, n) = PrimaryKey <$> table <*> pure n
where table = findTable (QualifiedIdentifier s t) tabs where table = M.lookup (QualifiedIdentifier s t) tabs
-- returns all the primary and foreign key columns which are referenced in views -- returns all the primary and foreign key columns which are referenced in views
pfkSourceColumns :: [Column] -> Bool -> SQL.Statement ([Schema], [Schema]) [SourceColumn] pfkSourceColumns :: [Column] -> Bool -> SQL.Statement ([Schema], [Schema]) [SourceColumn]
+5 -4
View File
@@ -11,7 +11,8 @@ module PostgREST.DbStructure.Relationship
import qualified Data.Aeson as JSON import qualified Data.Aeson as JSON
import PostgREST.DbStructure.Table (Column (..), Table (..)) import PostgREST.DbStructure.Identifiers (QualifiedIdentifier)
import PostgREST.DbStructure.Table (Column (..), Table)
import Protolude import Protolude
@@ -23,9 +24,9 @@ import Protolude
-- --
-- TODO merge relColumns and relForeignColumns to a tuple or Data.Bimap -- TODO merge relColumns and relForeignColumns to a tuple or Data.Bimap
data Relationship = Relationship data Relationship = Relationship
{ relTable :: Table { relTable :: QualifiedIdentifier
, relColumns :: [Column] , relColumns :: [Column]
, relForeignTable :: Table , relForeignTable :: QualifiedIdentifier
, relForeignColumns :: [Column] , relForeignColumns :: [Column]
, relCardinality :: Cardinality , relCardinality :: Cardinality
} }
@@ -44,7 +45,7 @@ type FKConstraint = Text
-- | Junction table on an M2M relationship -- | Junction table on an M2M relationship
data Junction = Junction data Junction = Junction
{ junTable :: Table { junTable :: QualifiedIdentifier
, junConstraint1 :: FKConstraint , junConstraint1 :: FKConstraint
, junColumns1 :: [Column] , junColumns1 :: [Column]
, junConstraint2 :: FKConstraint , junConstraint2 :: FKConstraint
-4
View File
@@ -4,7 +4,6 @@
module PostgREST.DbStructure.Table module PostgREST.DbStructure.Table
( Column(..) ( Column(..)
, Table(..) , Table(..)
, tableQi
, TablesMap , TablesMap
) where ) where
@@ -34,9 +33,6 @@ data Table = Table
instance Eq Table where instance Eq Table where
Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2 Table{tableSchema=s1,tableName=n1} == Table{tableSchema=s2,tableName=n2} = s1 == s2 && n1 == n2
tableQi :: Table -> QualifiedIdentifier
tableQi Table{tableSchema=s, tableName=n} = QualifiedIdentifier s n
data Column = Column data Column = Column
{ colTable :: Table { colTable :: Table
, colName :: FieldName , colName :: FieldName
+8 -7
View File
@@ -34,12 +34,13 @@ import qualified PostgREST.ContentType as ContentType
import PostgREST.Request.Types (ApiRequestError (..), import PostgREST.Request.Types (ApiRequestError (..),
QPError (..)) QPError (..))
import PostgREST.DbStructure.Identifiers (QualifiedIdentifier (..))
import PostgREST.DbStructure.Proc (ProcDescription (..), import PostgREST.DbStructure.Proc (ProcDescription (..),
ProcParam (..)) ProcParam (..))
import PostgREST.DbStructure.Relationship (Cardinality (..), import PostgREST.DbStructure.Relationship (Cardinality (..),
Junction (..), Junction (..),
Relationship (..)) Relationship (..))
import PostgREST.DbStructure.Table (Column (..), Table (..)) import PostgREST.DbStructure.Table (Column (..))
import Protolude import Protolude
@@ -153,28 +154,28 @@ compressedRel Relationship{..} =
fmtEls els = "(" <> T.intercalate ", " els <> ")" fmtEls els = "(" <> T.intercalate ", " els <> ")"
in in
JSON.object $ JSON.object $
("embedding" .= (tableName relTable <> " with " <> tableName relForeignTable :: Text)) ("embedding" .= (qiName relTable <> " with " <> qiName relForeignTable :: Text))
: case relCardinality of : case relCardinality of
M2M Junction{..} -> [ M2M Junction{..} -> [
"cardinality" .= ("many-to-many" :: Text) "cardinality" .= ("many-to-many" :: Text)
, "relationship" .= (tableName junTable <> " using " <> junConstraint1 <> fmtEls (colName <$> junColumns1) <> " and " <> junConstraint2 <> fmtEls (colName <$> junColumns2)) , "relationship" .= (qiName junTable <> " using " <> junConstraint1 <> fmtEls (colName <$> junColumns1) <> " and " <> junConstraint2 <> fmtEls (colName <$> junColumns2))
] ]
M2O cons -> [ M2O cons -> [
"cardinality" .= ("many-to-one" :: Text) "cardinality" .= ("many-to-one" :: Text)
, "relationship" .= (cons <> " using " <> tableName relTable <> fmtEls (colName <$> relColumns) <> " and " <> tableName relForeignTable <> fmtEls (colName <$> relForeignColumns)) , "relationship" .= (cons <> " using " <> qiName relTable <> fmtEls (colName <$> relColumns) <> " and " <> qiName relForeignTable <> fmtEls (colName <$> relForeignColumns))
] ]
O2M cons -> [ O2M cons -> [
"cardinality" .= ("one-to-many" :: Text) "cardinality" .= ("one-to-many" :: Text)
, "relationship" .= (cons <> " using " <> tableName relTable <> fmtEls (colName <$> relColumns) <> " and " <> tableName relForeignTable <> fmtEls (colName <$> relForeignColumns)) , "relationship" .= (cons <> " using " <> qiName relTable <> fmtEls (colName <$> relColumns) <> " and " <> qiName relForeignTable <> fmtEls (colName <$> relForeignColumns))
] ]
relHint :: [Relationship] -> Text relHint :: [Relationship] -> Text
relHint rels = T.intercalate ", " (hintList <$> rels) relHint rels = T.intercalate ", " (hintList <$> rels)
where where
hintList Relationship{..} = hintList Relationship{..} =
let buildHint rel = "'" <> tableName relForeignTable <> "!" <> rel <> "'" in let buildHint rel = "'" <> qiName relForeignTable <> "!" <> rel <> "'" in
case relCardinality of case relCardinality of
M2M Junction{..} -> buildHint (tableName junTable) M2M Junction{..} -> buildHint (qiName junTable)
M2O cons -> buildHint cons M2O cons -> buildHint cons
O2M cons -> buildHint cons O2M cons -> buildHint cons
+4 -2
View File
@@ -29,12 +29,14 @@ import PostgREST.Config (AppConfig (..), Proxy (..),
isMalformedProxyUri, toURI) isMalformedProxyUri, toURI)
import PostgREST.DbStructure (DbStructure (..), import PostgREST.DbStructure (DbStructure (..),
tableCols, tablePKCols) tableCols, tablePKCols)
import PostgREST.DbStructure.Identifiers (QualifiedIdentifier (..))
import PostgREST.DbStructure.Proc (ProcDescription (..), import PostgREST.DbStructure.Proc (ProcDescription (..),
ProcParam (..)) ProcParam (..))
import PostgREST.DbStructure.Relationship (Cardinality (..), import PostgREST.DbStructure.Relationship (Cardinality (..),
PrimaryKey (..), PrimaryKey (..),
Relationship (..)) Relationship (..))
import PostgREST.DbStructure.Table (Column (..), Table (..), TablesMap) import PostgREST.DbStructure.Table (Column (..), Table (..),
TablesMap)
import PostgREST.Version (docsVersion, prettyVersion) import PostgREST.Version (docsVersion, prettyVersion)
import PostgREST.ContentType import PostgREST.ContentType
@@ -103,7 +105,7 @@ makeProperty rels pks c = (colName c, Inline s)
_ -> False _ -> False
) rels ) rels
fCol = colName <$> (headMay . relForeignColumns =<< rel) fCol = colName <$> (headMay . relForeignColumns =<< rel)
fTbl = tableName . relForeignTable <$> rel fTbl = qiName . relForeignTable <$> rel
fTblCol = (,) <$> fTbl <*> fCol fTblCol = (,) <$> fTbl <*> fCol
in in
(\(a, b) -> T.intercalate "" ["This is a Foreign Key to `", a, ".", b, "`.<fk table='", a, "' column='", b, "'/>"]) <$> fTblCol (\(a, b) -> T.intercalate "" ["This is a Foreign Key to `", a, ".", b, "`.<fk table='", a, "' column='", b, "'/>"]) <$> fTblCol
+1 -2
View File
@@ -25,7 +25,6 @@ import PostgREST.DbStructure.Identifiers (QualifiedIdentifier (..))
import PostgREST.DbStructure.Proc (ProcParam (..)) import PostgREST.DbStructure.Proc (ProcParam (..))
import PostgREST.DbStructure.Relationship (Cardinality (..), import PostgREST.DbStructure.Relationship (Cardinality (..),
Relationship (..)) Relationship (..))
import PostgREST.DbStructure.Table (Table (..))
import PostgREST.Request.Preferences (PreferResolution (..)) import PostgREST.Request.Preferences (PreferResolution (..))
import PostgREST.Query.SqlFragment import PostgREST.Query.SqlFragment
@@ -51,7 +50,7 @@ readRequestToQuery (Node (Select colSelects mainQi tblAlias implJoins logicFores
(joins, selects) = foldr getJoinsSelects ([],[]) forest (joins, selects) = foldr getJoinsSelects ([],[]) forest
getJoinsSelects :: ReadRequest -> ([SQL.Snippet], [SQL.Snippet]) -> ([SQL.Snippet], [SQL.Snippet]) getJoinsSelects :: ReadRequest -> ([SQL.Snippet], [SQL.Snippet]) -> ([SQL.Snippet], [SQL.Snippet])
getJoinsSelects rr@(Node (_, (name, Just Relationship{relCardinality=card,relTable=Table{tableName=table}}, alias, _, joinType, _)) _) (joins,selects) = getJoinsSelects rr@(Node (_, (name, Just Relationship{relCardinality=card,relTable=QualifiedIdentifier{qiName=table}}, alias, _, joinType, _)) _) (joins,selects) =
let subquery = readRequestToQuery rr in let subquery = readRequestToQuery rr in
case card of case card of
M2O _ -> M2O _ ->
+12 -13
View File
@@ -37,8 +37,7 @@ import PostgREST.DbStructure.Proc (ProcDescription (..),
import PostgREST.DbStructure.Relationship (Cardinality (..), import PostgREST.DbStructure.Relationship (Cardinality (..),
Junction (..), Junction (..),
Relationship (..)) Relationship (..))
import PostgREST.DbStructure.Table (Column (..), Table (..), import PostgREST.DbStructure.Table (Column (..))
tableQi)
import PostgREST.Error (Error (..)) import PostgREST.Error (Error (..))
import PostgREST.Query.SqlFragment (sourceCTEName) import PostgREST.Query.SqlFragment (sourceCTEName)
import PostgREST.RangeQuery (NonnegRange, allRange, import PostgREST.RangeQuery (NonnegRange, allRange,
@@ -88,7 +87,7 @@ rootWithRels schema rootTableName allRels action = case action of
-- findRel can find relationships with sourceCTEName. -- findRel can find relationships with sourceCTEName.
toSourceRel :: Relationship -> Maybe Relationship toSourceRel :: Relationship -> Maybe Relationship
toSourceRel r@Relationship{relTable=t} toSourceRel r@Relationship{relTable=t}
| rootTableName == tableName t = Just $ r {relTable=t {tableName=_sourceCTEName}} | rootTableName == qiName t = Just $ r {relTable=t {qiName=_sourceCTEName}}
| otherwise = Nothing | otherwise = Nothing
-- Build the initial tree with a Depth attribute so when a self join occurs we -- Build the initial tree with a Depth attribute so when a self join occurs we
@@ -131,7 +130,7 @@ addRels :: Schema -> [Relationship] -> Maybe ReadRequest -> ReadRequest -> Eithe
addRels schema allRels parentNode (Node (query@Select{from=tbl}, (nodeName, _, alias, hint, joinType, depth)) forest) = addRels schema allRels parentNode (Node (query@Select{from=tbl}, (nodeName, _, alias, hint, joinType, depth)) forest) =
case parentNode of case parentNode of
Just (Node (Select{from=parentNodeQi}, _) _) -> Just (Node (Select{from=parentNodeQi}, _) _) ->
let newFrom r = if qiName tbl == nodeName then tableQi (relForeignTable r) else tbl let newFrom r = if qiName tbl == nodeName then relForeignTable r else tbl
newReadNode = (\r -> (query{from=newFrom r}, (nodeName, Just r, alias, hint, joinType, depth))) <$> rel newReadNode = (\r -> (query{from=newFrom r}, (nodeName, Just r, alias, hint, joinType, depth))) <$> rel
rel = findRel schema allRels (qiName parentNodeQi) nodeName hint rel = findRel schema allRels (qiName parentNodeQi) nodeName hint
in in
@@ -175,25 +174,25 @@ findRel schema allRels origin target hint =
M2O cons -> tar == Just cons M2O cons -> tar == Just cons
_ -> False _ -> False
matchJunction hint_ card = case card of matchJunction hint_ card = case card of
M2M Junction{junTable} -> hint_ == Just (tableName junTable) M2M Junction{junTable} -> hint_ == Just (qiName junTable)
_ -> False _ -> False
rel = filter ( rel = filter (
\Relationship{..} -> \Relationship{..} ->
-- Both relationship ends need to be on the exposed schema -- Both relationship ends need to be on the exposed schema
schema == tableSchema relTable && schema == tableSchema relForeignTable && schema == qiSchema relTable && schema == qiSchema relForeignTable &&
( (
-- /projects?select=clients(*) -- /projects?select=clients(*)
origin == tableName relTable && -- projects origin == qiName relTable && -- projects
target == tableName relForeignTable || -- clients target == qiName relForeignTable || -- clients
-- /projects?select=projects_client_id_fkey(*) -- /projects?select=projects_client_id_fkey(*)
( (
origin == tableName relTable && -- projects origin == qiName relTable && -- projects
matchConstraint (Just target) relCardinality -- projects_client_id_fkey matchConstraint (Just target) relCardinality -- projects_client_id_fkey
) || ) ||
-- /projects?select=client_id(*) -- /projects?select=client_id(*)
( (
origin == tableName relTable && -- projects origin == qiName relTable && -- projects
matchFKSingleCol (Just target) relColumns -- client_id matchFKSingleCol (Just target) relColumns -- client_id
) )
) && ( ) && (
@@ -217,7 +216,7 @@ addJoinConditions previousAlias (Node node@(query@Select{from=tbl}, nodeProps@(_
case rel of case rel of
Just r@Relationship{relCardinality=M2M Junction{junTable}} -> Just r@Relationship{relCardinality=M2M Junction{junTable}} ->
let rq = augmentQuery r in let rq = augmentQuery r in
Node (rq{implicitJoins=tableQi junTable:implicitJoins rq}, nodeProps) <$> updatedForest Node (rq{implicitJoins=junTable:implicitJoins rq}, nodeProps) <$> updatedForest
Just r -> Node (augmentQuery r, nodeProps) <$> updatedForest Just r -> Node (augmentQuery r, nodeProps) <$> updatedForest
Nothing -> Node node <$> updatedForest Nothing -> Node node <$> updatedForest
where where
@@ -235,9 +234,9 @@ addJoinConditions previousAlias (Node node@(query@Select{from=tbl}, nodeProps@(_
-- previousAlias and newAlias are used in the case of self joins -- previousAlias and newAlias are used in the case of self joins
getJoinConditions :: Maybe Alias -> Maybe Alias -> Relationship -> [JoinCondition] getJoinConditions :: Maybe Alias -> Maybe Alias -> Relationship -> [JoinCondition]
getJoinConditions previousAlias newAlias (Relationship Table{tableSchema=tSchema, tableName=tN} cols Table{tableName=ftN} fCols card) = getJoinConditions previousAlias newAlias (Relationship QualifiedIdentifier{qiSchema=tSchema, qiName=tN} cols QualifiedIdentifier{qiName=ftN} fCols card) =
case card of case card of
M2M (Junction Table{tableName=jtn} _ jc1 _ jc2) -> M2M (Junction QualifiedIdentifier{qiName=jtn} _ jc1 _ jc2) ->
zipWith (toJoinCondition tN jtn) cols jc1 ++ zipWith (toJoinCondition ftN jtn) fCols jc2 zipWith (toJoinCondition tN jtn) cols jc1 ++ zipWith (toJoinCondition ftN jtn) fCols jc2
_ -> _ ->
zipWith (toJoinCondition tN ftN) cols fCols zipWith (toJoinCondition tN ftN) cols fCols
+1 -4
View File
@@ -27,9 +27,6 @@ spec =
request methodGet "/" request methodGet "/"
[("Accept", "application/json")] "" `shouldRespondWith` [("Accept", "application/json")] "" `shouldRespondWith`
[json| { [json| {
"tableName": "orders_view", "tableSchema": "test", "qiSchema":"test","qiName":"orders_view"
"tableDeletable": true, "tableUpdatable": true,
"tableIsView":true, "tableInsertable": true,
"tableDescription": null
} |] } |]
{ matchHeaders = [matchContentTypeJson] } { matchHeaders = [matchContentTypeJson] }