diff --git a/src/PostgREST/Plan.hs b/src/PostgREST/Plan.hs index 4acedf4264..c2e4e59136 100644 --- a/src/PostgREST/Plan.hs +++ b/src/PostgREST/Plan.hs @@ -337,7 +337,6 @@ readPlan qi@QualifiedIdentifier{..} AppConfig{configDbMaxRows, configDbAggregate hoistSpreadAggFunctions =<< addRelSelects =<< addNullEmbedFilters =<< - validateSpreadEmbeds =<< addRelatedOrders =<< addAliases =<< expandStars ctx =<< @@ -890,15 +889,6 @@ resolveLogicTree ctx (Expr b op lts) = CoercibleExpr b op (map (resolveLogicTree resolveFilter :: ResolverContext -> Filter -> CoercibleFilter resolveFilter ctx (Filter fld opExpr) = CoercibleFilter{field=resolveQueryInputField ctx fld, opExpr=opExpr} --- Validates that spread embeds are only done on to-one relationships -validateSpreadEmbeds :: ReadPlanTree -> Either ApiRequestError ReadPlanTree -validateSpreadEmbeds (Node rp@ReadPlan{relToParent=Nothing} forest) = Node rp <$> validateSpreadEmbeds `traverse` forest -validateSpreadEmbeds (Node rp@ReadPlan{relIsSpread,relToParent=Just rel,relName} forest) = do - validRP <- if relIsSpread && not (relIsToOne rel) - then Left $ SpreadNotToOne (qiName $ relTable rel) relName -- TODO using relTable is not entirely right because ReadPlan might have an alias, need to store the parent alias on ReadPlan - else Right rp - Node validRP <$> validateSpreadEmbeds `traverse` forest - -- Find a Node of the Tree and apply a function to it updateNode :: (a -> ReadPlanTree -> ReadPlanTree) -> (EmbedPath, a) -> Either ApiRequestError ReadPlanTree -> Either ApiRequestError ReadPlanTree updateNode f ([], a) rr = f a <$> rr diff --git a/src/PostgREST/Query/QueryBuilder.hs b/src/PostgREST/Query/QueryBuilder.hs index 1729f0dce4..57b50b2b6f 100644 --- a/src/PostgREST/Query/QueryBuilder.hs +++ b/src/PostgREST/Query/QueryBuilder.hs @@ -27,7 +27,8 @@ import PostgREST.Config.PgVersion (PgVersion, pgVersion130) import PostgREST.SchemaCache.Identifiers (QualifiedIdentifier (..)) import PostgREST.SchemaCache.Relationship (Cardinality (..), Junction (..), - Relationship (..)) + Relationship (..), + relIsToOne) import PostgREST.SchemaCache.Routine (RoutineParam (..)) import PostgREST.ApiRequest.Types @@ -43,6 +44,9 @@ import Protolude readPlanToQuery :: ReadPlanTree -> SQL.Snippet readPlanToQuery node@(Node ReadPlan{select,from=mainQi,fromAlias,where_=logicForest,order, range_=readRange, relToParent, relJoinConds, relSelect} forest) = "SELECT " <> + -- Needs to validate if: "relIsSpread && (relIsToOne <$> relToParent == Just False)" + -- then use json_agg() in pgFmtSelectItem qi + -- It will not apply for *, check if something can be done here (maybe nest/unnest, use the Schema Cache or disallow completely) intercalateSnippet ", " ((pgFmtSelectItem qi <$> (if null select && null forest then defSelect else select)) ++ joinsSelects) <> " " <> fromFrag <> " " <> intercalateSnippet " " joins <> " " <>