on dev help sign in
Merge pull request #126 from morphismtech/dev-with-recursive2

withRecursive

commit151df3440876b6d488f63a40191d14dfbbb509bb authorEitan Chatav <eitan.chatav@gmail.com> dateSun 14 Apr 2019, 12:52 (8 years ago) parent85e2bb99ca5584
2 files changed+38
squeal-postgresql/src/Squeal/PostgreSQL/Alias.hs+8 squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+30
squeal-postgresql/src/Squeal/PostgreSQL/Alias.hs+8
@@ -40,6 +40,7 @@ module Squeal.PostgreSQL.Alias
4040 , Aliased (As)
4141 , Aliasable (as)
4242 , renderAliased
43+ , RenderFields (..)
4344 , Has
4445 , HasUnique
4546 , HasAll
@@ -166,6 +167,13 @@ renderAliased
166167renderAliased render (expression `As` alias) =
167168 render expression <> " AS " <> renderSQL alias
168169
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+
169177-- | @HasUnique alias fields field@ is a constraint that proves that
170178-- @fields@ is a singleton of @alias ::: field@.
171179type HasUnique alias fields field = fields ~ '[alias ::: field]
squeal-postgresql/src/Squeal/PostgreSQL/Query.hs+30
@@ -53,6 +53,7 @@ module Squeal.PostgreSQL.Query
5353 -- ** With
5454 , With (..)
5555 , CommonTableExpression (..)
56+ , withRecursive
5657 -- * Table Expressions
5758 , TableExpression (..)
5859 , from
@@ -965,3 +966,32 @@ instance With (Query outer) where
965966 with Done query = query
966967 with ctes query = UnsafeQuery $
967968 "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