Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/PostgREST/ApiRequest/QueryParams.hs
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,8 @@ pTreePath = do
pFieldForest :: Parser [Tree SelectItem]
pFieldForest = pFieldTree `sepBy` lexeme (char ',')
where
pFieldTree = Node <$> try pSpreadRelationSelect <*> between (char '(') (char ')') pFieldForest <|>
pFieldTree = Node <$> try pHoistedRelationSelect <*> between (char '(') (char ')') pFieldForest <|>
Node <$> try pSpreadRelationSelect <*> between (char '(') (char ')') pFieldForest <|>
Node <$> try pRelationSelect <*> between (char '(') (char ')') pFieldForest <|>
Node <$> pFieldSelect <*> pure []

Expand Down Expand Up @@ -582,6 +583,13 @@ pSpreadRelationSelect = lexeme $ do
try (void $ lookAhead (string "("))
return $ SpreadRelation name hint jType

pHoistedRelationSelect :: Parser SelectItem
pHoistedRelationSelect = lexeme $ do
name <- string "^" >> pFieldName
(hint, jType) <- pEmbedParams
try (void $ lookAhead (string "("))
return $ HoistedRelation name hint jType

pEmbedParams :: Parser (Maybe Hint, Maybe JoinType)
pEmbedParams = do
prm1 <- optionMaybe pEmbedParam
Expand Down
6 changes: 6 additions & 0 deletions src/PostgREST/ApiRequest/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,12 @@ data SelectItem
, selHint :: Maybe Hint
, selJoinType :: Maybe JoinType
}
-- | The value in `/tbl?select=^another_tbl(*)`
| HoistedRelation
{ selRelation :: FieldName
, selHint :: Maybe Hint
, selJoinType :: Maybe JoinType
}
deriving (Eq, Show)

type NodeName = Text
Expand Down
130 changes: 75 additions & 55 deletions src/PostgREST/Plan.hs

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions src/PostgREST/Plan/ReadPlan.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
, relAlias :: Maybe Alias
, relAggAlias :: Alias
, relHint :: Maybe Hint
, relIsHoisted :: Bool

Check warning on line 46 in src/PostgREST/Plan/ReadPlan.hs

View check run for this annotation

Codecov / codecov/patch

src/PostgREST/Plan/ReadPlan.hs#L46

Added line #L46 was not covered by tests
, relJoinType :: Maybe JoinType
, relSpread :: Maybe SpreadType
, relSelect :: [RelSelectField]
Expand Down
15 changes: 15 additions & 0 deletions src/PostgREST/Plan/Types.hs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
, RelSelectField(..)
, RelJsonEmbedMode(..)
, SpreadSelectField(..)
, HoistedSelectField(..)
, SpreadType(..)
) where

Expand Down Expand Up @@ -102,6 +103,10 @@
{ rsSpreadSel :: [SpreadSelectField]
, rsAggAlias :: Alias
}
| Hoisted
{ rsHoistedSel :: [HoistedSelectField]

Check warning on line 107 in src/PostgREST/Plan/Types.hs

View check run for this annotation

Codecov / codecov/patch

src/PostgREST/Plan/Types.hs#L107

Added line #L107 was not covered by tests
, rsAggAlias :: Alias
}
deriving (Eq, Show)

data SpreadSelectField =
Expand All @@ -113,6 +118,16 @@
}
deriving (Eq, Show)

-- TODO(draft): DRY
data HoistedSelectField =
HoistedSelectField
{ hsSelName :: FieldName
, hsSelAggFunction :: Maybe AggregateFunction
, hsSelAggCast :: Maybe Cast
, hsSelAlias :: Maybe Alias

Check warning on line 127 in src/PostgREST/Plan/Types.hs

View check run for this annotation

Codecov / codecov/patch

src/PostgREST/Plan/Types.hs#L126-L127

Added lines #L126 - L127 were not covered by tests
}
deriving (Eq, Show)

Check warning on line 129 in src/PostgREST/Plan/Types.hs

View check run for this annotation

Codecov / codecov/patch

src/PostgREST/Plan/Types.hs#L129

Added line #L129 was not covered by tests

data SpreadType
= ToOneSpread
| ToManySpread
Expand Down
4 changes: 4 additions & 0 deletions src/PostgREST/Query/QueryBuilder.hs
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ getJoinSelects (Node ReadPlan{relSelect} _) =
Just $ "row_to_json(" <> aggAlias <> ".*)::jsonb AS " <> pgFmtIdent rsSelName
JsonEmbed{rsSelName, rsEmbedMode = JsonArray} ->
Just $ "COALESCE( " <> aggAlias <> "." <> aggAlias <> ", '[]') AS " <> pgFmtIdent rsSelName
Hoisted{rsHoistedSel, rsAggAlias} ->
Just $ intercalateSnippet ", " (pgFmtHoistedSelectItem rsAggAlias <$> rsHoistedSel)
Spread{rsSpreadSel, rsAggAlias} ->
Just $ intercalateSnippet ", " (pgFmtSpreadSelectItem rsAggAlias <$> rsSpreadSel)

Expand All @@ -108,6 +110,8 @@ getJoin fld node@(Node ReadPlan{relJoinType, relSpread} _) =
case fld of
JsonEmbed{rsEmbedMode = JsonObject} ->
correlatedSubquery subquery aggAlias "TRUE"
Hoisted{} ->
correlatedSubquery subquery aggAlias "TRUE"
Spread{rsSpreadSel, rsAggAlias} ->
case relSpread of
Just (ToManySpread _ sprOrder) ->
Expand Down
24 changes: 22 additions & 2 deletions src/PostgREST/Query/SqlFragment.hs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ module PostgREST.Query.SqlFragment
, orderF
, pgFmtColumn
, pgFmtFilter
, pgFmtHoistedSelectItem
, pgFmtIdent
, pgFmtJoinCondition
, pgFmtLogicTree
Expand Down Expand Up @@ -79,6 +80,7 @@ import PostgREST.Plan.Types (CoercibleField (..),
CoercibleLogicTree (..),
CoercibleOrderTerm (..),
CoercibleSelectField (..),
HoistedSelectField (..),
RelSelectField (..),
SpreadSelectField (..),
ToTsVector (..),
Expand Down Expand Up @@ -281,8 +283,13 @@ pgFmtSpreadSelectItem :: Alias -> SpreadSelectField -> SQL.Snippet
pgFmtSpreadSelectItem aggAlias SpreadSelectField{ssSelName, ssSelAggFunction, ssSelAggCast, ssSelAlias} =
pgFmtApplyAggregate ssSelAggFunction ssSelAggCast (pgFmtFullSelName aggAlias ssSelName) <> pgFmtAs ssSelAlias

-- TODO(draft): DRY
pgFmtHoistedSelectItem :: Alias -> HoistedSelectField -> SQL.Snippet
pgFmtHoistedSelectItem aggAlias HoistedSelectField{hsSelName, hsSelAggFunction, hsSelAggCast, hsSelAlias} =
pgFmtApplyAggregate hsSelAggFunction hsSelAggCast (pgFmtFullSelName aggAlias hsSelName) <> pgFmtAs hsSelAlias

pgFmtApplyAggregate :: Maybe AggregateFunction -> Maybe Cast -> SQL.Snippet -> SQL.Snippet
pgFmtApplyAggregate Nothing _ snippet = snippet
pgFmtApplyAggregate Nothing _ snippet =snippet
pgFmtApplyAggregate (Just agg) aggCast snippet =
pgFmtApplyCast aggCast aggregatedSnippet
where
Expand Down Expand Up @@ -458,7 +465,7 @@ groupF qi select relSelect
| otherwise = " GROUP BY " <> intercalateSnippet ", " groupTerms
where
noSelectsAreAggregated = null $ [s | s@(CoercibleSelectField { csAggFunction = Just _ }) <- select]
noRelSelectsAreAggregated = all (\case Spread sels _ -> all (isNothing . ssSelAggFunction) sels; _ -> True) relSelect
noRelSelectsAreAggregated = all (\case Hoisted sels _ -> all (isNothing . hsSelAggFunction) sels; _ -> True) relSelect
groupTermsFromSelect = mapMaybe (pgFmtGroup qi) select
groupTermsFromRelSelect = mapMaybe groupTermFromRelSelectField relSelect
groupTerms = groupTermsFromSelect ++ groupTermsFromRelSelect
Expand All @@ -477,6 +484,19 @@ groupTermFromRelSelectField (Spread { rsSpreadSel, rsAggAlias }) =
processField SpreadSelectField{ssSelName, ssSelAlias} =
Just $ pgFmtIdent rsAggAlias <> "." <> pgFmtIdent (fromMaybe ssSelName ssSelAlias)
groupTerms = mapMaybe processField rsSpreadSel
-- TODO(draft): DRY
groupTermFromRelSelectField (Hoisted { rsHoistedSel, rsAggAlias }) =
if null groupTerms
then Nothing
else
Just $ intercalateSnippet ", " groupTerms
where
processField :: HoistedSelectField -> Maybe SQL.Snippet
processField HoistedSelectField{hsSelAggFunction = Just _} = Nothing
processField HoistedSelectField{hsSelName, hsSelAlias} =
Just $ pgFmtIdent rsAggAlias <> "." <> pgFmtIdent (fromMaybe hsSelName hsSelAlias)
groupTerms = mapMaybe processField rsHoistedSel


pgFmtGroup :: QualifiedIdentifier -> CoercibleSelectField -> Maybe SQL.Snippet
pgFmtGroup _ CoercibleSelectField{csAggFunction=Just _} = Nothing
Expand Down
Loading
Loading