@@ -118,6 +118,10 @@ module Squeal.PostgreSQL.Query
118 , rowAllGte
118 , rowAllGte
120 , rowAnyGte
120 , rowAnyGte
122+ , CommonTableExpression (..)
123import Control.DeepSeq
127import Control.DeepSeq
@@ -324,6 +328,43 @@ let
324in printSQL query
328in printSQL query
326(SELECT * FROM "tab" AS "tab") UNION ALL (SELECT * FROM "tab" AS "tab")
330(SELECT * FROM "tab" AS "tab") UNION ALL (SELECT * FROM "tab" AS "tab")
337+ '[ "orders" ::: 'View
338+ '[ "region" ::: 'NotNull 'PGtext
339+ , "product" ::: 'NotNull 'PGtext
340+ , "quantity" ::: 'NotNull 'PGint8
341+ , "amount" ::: 'NotNull 'PGnumeric ] ]
342+ '[ 'NotNull 'PGint8 ]
343+ '[ "region" ::: 'NotNull 'PGtext
344+ , "product" ::: 'NotNull 'PGtext
345+ , "product_units" ::: 'NotNull 'PGint8
346+ , "product_sales" ::: 'NotNull 'PGnumeric ]
348+ CommonTableExpression
349+ (((select (#region :* sum_ @'PGnumeric #amount `as` #total_sales)
350+ (from (view #orders) & groupBy #region))
351+ `as` #regional_sales)) :>>
352+ CommonTableExpression
353+ (((select (#region `as` #region)
354+ (from (view #regional_sales) & where_ (#total_sales .> param @1)))
355+ `as` #top_regions)) :>> Done
359+ sum_ #quantity `as` #product_units :*
360+ sum_ #amount `as` #product_sales
361+ ) (from (view #orders)
362+ & where_ (#region `in_` select #region (from (view #top_regions)))
363+ & groupBy (#region :* #product))
328newtype Query
369newtype Query
329 (schema :: SchemaType)
370 (schema :: SchemaType)
@@ -1287,3 +1328,47 @@ rowAnyGte
1287 -> Query schema params row
1328 -> Query schema params row
1288 -> Condition schema from grp params
1329 -> Condition schema from grp params
1289rowAnyGte = unsafeRowSubqueryExpression "ANY >="
1330rowAnyGte = unsafeRowSubqueryExpression "ANY >="
1332+data CommonTableExpression statement
1333+ (params :: [NullityType])
1334+ (schema0 :: SchemaType)
1335+ (schema1 :: SchemaType) where
1336+ CommonTableExpression
1337+ :: Aliased (statement schema params) (alias ::: cte)
1338+ -> CommonTableExpression
1339+ statement params schema (alias ::: 'View cte ': schema)
1340+instance KnownSymbol alias => Aliasable alias (statement schema params cte)
1341+ (CommonTableExpression statement params schema
1342+ (alias ::: 'View cte ': schema)) where
1343+ statement `as` alias = CommonTableExpression (statement `As` alias)
1344+instance KnownSymbol alias => Aliasable alias (statement schema params cte)
1345+ (AlignedList (CommonTableExpression statement params) schema
1346+ (alias ::: 'View cte ': schema)) where
1347+ statement `as` alias = statement `as` alias :>> Done
1350+ :: (forall sch ps row. statement ps sch row -> ByteString)
1351+ -> CommonTableExpression statement params schema0 schema1 -> ByteString
1352+renderCte renderStatement (CommonTableExpression (statement `As` alias)) =
1353+ renderAlias alias <+> "AS" <+> parenthesized (renderStatement statement)
1356+ :: (forall sch ps row. statement ps sch row -> ByteString)
1357+ -> CommonTableExpression statement params schema0 schema1
1358+ -> AlignedList (CommonTableExpression statement params) schema1 schema2
1360+renderCtes renderStatement cte ctes =
1361+ renderCte renderStatement cte <+> case ctes of
1363+ cte' :>> ctes' -> "," <+>
1364+ renderCtes renderStatement cte' ctes'
1366+class With' statement where
1368+ :: AlignedList (CommonTableExpression statement params) schema0 schema1
1369+ -> statement schema1 params row
1370+ -> statement schema0 params row
1371+instance With' Query where
1372+ with' Done query = query
1373+ with' (cte :>> ctes) query = UnsafeQuery $
1374+ "WITH" <+> renderCtes renderQuery cte ctes <+> renderQuery query