on dev help sign in
Merge pull request #126 from morphismtech/dev-with-recursive2
151df34Eitan Chatav
squeal-postgresql/src/Squeal/PostgreSQL/Alias.hs+8
@@ -40,6 +40,7 @@ module Squeal.PostgreSQL.Alias
40 , Aliased (As)
40 , Aliased (As)
41 , Aliasable (as)
41 , Aliasable (as)
42 , renderAliased
42 , renderAliased
43+ , RenderFields (..)
43 , Has
44 , Has
44 , HasUnique
45 , HasUnique
45 , HasAll
46 , HasAll
@@ -166,6 +167,13 @@ renderAliased
166renderAliased render (expression `As` alias) =
167renderAliased render (expression `As` alias) =
167 render expression <> " AS " <> renderSQL alias
168 render expression <> " AS " <> renderSQL alias
168
169
170+class RenderFields (row :: [(Symbol, ty)]) where
171+ renderFields :: p row -> [ByteString]
172+instance RenderFields '[] where renderFields _ = []
173+instance (KnownSymbol col, RenderFields row)
174+ => RenderFields (col ::: ty ': row) where
175+ renderFields _ = renderSQL (Alias @col) : renderFields (SOP.Proxy @row)
176+
169-- | @HasUnique alias fields field@ is a constraint that proves that
177-- | @HasUnique alias fields field@ is a constraint that proves that
170-- @fields@ is a singleton of @alias ::: field@.
178-- @fields@ is a singleton of @alias ::: field@.
171type HasUnique alias fields field = fields ~ '[alias ::: field]
179type HasUnique alias fields field = fields ~ '[alias ::: field]
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+30
@@ -53,6 +53,7 @@ module Squeal.PostgreSQL.Query
53 -- ** With
53 -- ** With
54 , With (..)
54 , With (..)
55 , CommonTableExpression (..)
55 , CommonTableExpression (..)
56+ , withRecursive
56 -- * Table Expressions
57 -- * Table Expressions
57 , TableExpression (..)
58 , TableExpression (..)
58 , from
59 , from
@@ -965,3 +966,32 @@ instance With (Query outer) where
965 with Done query = query
966 with Done query = query
966 with ctes query = UnsafeQuery $
967 with ctes query = UnsafeQuery $
967 "WITH" <+> renderSQL ctes <+> renderSQL query
968 "WITH" <+> renderSQL ctes <+> renderSQL query
969+
970+{- |
971+>>> import Data.Monoid (Sum (..))
972+>>> import Data.Int (Int32)
973+>>> :{
974+ let
975+ one :: Expr ('NotNull 'PGint4)
976+ one = 1
977+ query :: Query_ schema () (Sum Int32)
978+ query = withRecursive
979+ ( values_ (one `as` #n)
980+ `unionAll`
981+ select_ ((#n + 1) `as` #n)
982+ (from (common #t) & where_ (#n .< 100)) `as` #t )
983+ ( select_ (sum_ (All #n) `as` #getSum) (from (common #t) & groupBy Nil))
984+ in printSQL query
985+:}
986+WITH RECURSIVE "t"("n") AS ((SELECT * FROM (VALUES (1)) AS t ("n")) UNION ALL (SELECT ("n" + 1) AS "n" FROM "t" AS "t" WHERE ("n" < 100))) SELECT sum(ALL "n") AS "getSum" FROM "t" AS "t"
987+-}
988+withRecursive
989+ :: RenderFields recursive
990+ => Aliased (Query outer (cte ::: recursive ': commons) schemas params) (cte ::: recursive)
991+ -> Query outer (cte ::: recursive ': commons) schemas params row
992+ -> Query outer commons schemas params row
993+withRecursive (recursive `As` cte) query = UnsafeQuery $
994+ "WITH RECURSIVE" <+> renderSQL cte
995+ <> parenthesized (commaSeparated (renderFields recursive))
996+ <+> "AS" <+> parenthesized (renderSQL recursive)
997+ <+> renderSQL query