@@ -1,27 +1,77 @@
1+{-# language AllowAmbiguousTypes #-}
2+{-# language BlockArguments #-}
1{-# language DataKinds #-}
3{-# language DataKinds #-}
4+{-# language FlexibleContexts #-}
5+{-# language FlexibleInstances #-}
6+{-# language LambdaCase #-}
7+{-# language NamedFieldPuns #-}
8+{-# language RankNTypes #-}
9+{-# language ScopedTypeVariables #-}
2{-# language StandaloneKindSignatures #-}
10{-# language StandaloneKindSignatures #-}
11+{-# language TypeApplications #-}
3{-# language TypeFamilies #-}
12{-# language TypeFamilies #-}
4{-# language UndecidableInstances #-}
13{-# language UndecidableInstances #-}
14+{-# language ViewPatterns #-}
6module Rel8.Table.ADT
16module Rel8.Table.ADT
7 ( ADT( ADT )
17 ( ADT( ADT )
19+ , ConstructADT, constructADT
20+ , DeconstructADT, deconstructADT
21+ , InsertADT, insertADT
23+ , AggregateADT, aggregateADT
28+import Data.Bifunctor ( first )
29+import Data.Kind ( Constraint, Type )
30+import Data.List.NonEmpty ( NonEmpty( (:|) ) )
31+import Data.Type.Equality ( (:~:)( Refl ) )
12−import Prelude ()
32+import Prelude
35+import Rel8.Aggregate ( Col( Aggregation ), Aggregate, mapInputs )
36+import Rel8.Expr ( Col( DB ), Expr )
37+import Rel8.Expr.Aggregate ( groupByExpr )
38+import Rel8.Expr.Eq ( (==.) )
39+import Rel8.Expr.Null ( nullify, snull, unsafeUnnullify )
40+import Rel8.Expr.Opaleye ( fromPrimExpr, toPrimExpr )
41+import Rel8.Expr.Serialize ( litExpr )
42+import Rel8.Generic.Construction.ADT
44+ , GBuildADT, gbuildADT, gunbuildADT
45+ , GConstructADT, gconstructADT, gdeconstructADT
46+ , CorepConstructors, GConstructors, gcindex, gctabulate
47+ , CorepFields, GFields, gfindex, gftabulate
15import Rel8.Generic.Rel8able
49import Rel8.Generic.Rel8able
16 ( Rel8able, Algebra
50 ( Rel8able, Algebra
17 , GRep, GColumns, GContext, gfromColumns, gtoColumns
51 , GRep, GColumns, GContext, gfromColumns, gtoColumns
18 , GColumnsADT, gfromColumnsADT, gtoColumnsADT
52 , GColumnsADT, gfromColumnsADT, gtoColumnsADT
19 , greify, gunreify
53 , greify, gunreify
55+import qualified Rel8.Generic.Table.ADT as G
21import qualified Rel8.Kind.Algebra as K
56import qualified Rel8.Kind.Algebra as K
57+import Rel8.Kind.Necessity ( SNecessity( SOptional, SRequired ) )
22import Rel8.Schema.Context ( Col )
58import Rel8.Schema.Context ( Col )
59+import Rel8.Schema.Context.Nullify ( runTag )
60+import Rel8.Schema.HTable ( HTable )
61+import Rel8.Schema.HTable.Type ( HType( HType ) )
62+import Rel8.Schema.Insert ( Col( OptionalInsert, RequiredInsert ), Insert )
23import qualified Rel8.Schema.Kind as K
63import qualified Rel8.Schema.Kind as K
64+import Rel8.Schema.Name ( Col( NameCol ), Name( Name ) )
65+import Rel8.Schema.Null ( Nullity( Null, NotNull ) )
66+import Rel8.Schema.Spec ( SSpec( SSpec, necessity, nullity, info ) )
24−import Rel8.Schema.Reify ( hreify, hunreify )
67+import Rel8.Schema.Reify ( Col( Reify ), Reify, hreify, hunreify )
68+import Rel8.Schema.Result ( Result )
70+ ( TTable, TColumns, TUnreify
71+ , Table, fromColumns, toColumns, reify, unreify
73+import Rel8.Table.Bool ( case_ )
74+import Rel8.Type.Tag ( Tag )
27type ADT :: K.Rel8able -> K.Rel8able
77type ADT :: K.Rel8able -> K.Rel8able
@@ -44,3 +94,192 @@ instance Rel8able t => Rel8able (ADT t) where
45 greify (ADT a) = ADT (hreify a)
95 greify (ADT a) = ADT (hreify a)
46 gunreify (ADT a) = ADT (hunreify a)
96 gunreify (ADT a) = ADT (hunreify a)
99+type ConstructableADT :: K.Rel8able -> Constraint
101+ ( CorepConstructors TUnreify (GRep t (Reify Expr))
102+ , CorepConstructors TUnreify (GRep t (Reify Insert))
103+ , CorepFields TUnreify (GRep t (Reify Aggregate))
104+ , CorepFields TUnreify (GRep t (Reify Expr))
105+ , CorepFields TUnreify (GRep t (Reify Name))
106+ , G.GColumnsADT TColumns (GRep t (Reify Aggregate)) ~ GColumnsADT t
107+ , G.GColumnsADT TColumns (GRep t (Reify Expr)) ~ GColumnsADT t
108+ , G.GColumnsADT TColumns (GRep t (Reify Insert)) ~ GColumnsADT t
109+ , G.GColumnsADT TColumns (GRep t (Reify Name)) ~ GColumnsADT t
110+ , Functor (GConstructors TUnreify (GRep t (Reify Expr)))
111+ , Functor (GConstructors TUnreify (GRep t (Reify Insert)))
112+ , HTable (G.GColumnsADT TColumns (GRep t (Reify Result)))
113+ , GConstructableADT (TTable (Reify Aggregate)) TColumns TUnreify (Col (Reify Aggregate)) (GRep t (Reify Aggregate))
114+ , GConstructableADT (TTable (Reify Expr)) TColumns TUnreify (Col (Reify Expr)) (GRep t (Reify Expr))
115+ , GConstructableADT (TTable (Reify Insert)) TColumns TUnreify (Col (Reify Insert)) (GRep t (Reify Insert))
116+ , GConstructableADT (TTable (Reify Name)) TColumns TUnreify (Col (Reify Name)) (GRep t (Reify Name))
118+ => ConstructableADT t
120+ ( CorepConstructors TUnreify (GRep t (Reify Expr))
121+ , CorepConstructors TUnreify (GRep t (Reify Insert))
122+ , CorepFields TUnreify (GRep t (Reify Aggregate))
123+ , CorepFields TUnreify (GRep t (Reify Expr))
124+ , CorepFields TUnreify (GRep t (Reify Name))
125+ , G.GColumnsADT TColumns (GRep t (Reify Aggregate)) ~ GColumnsADT t
126+ , G.GColumnsADT TColumns (GRep t (Reify Expr)) ~ GColumnsADT t
127+ , G.GColumnsADT TColumns (GRep t (Reify Insert)) ~ GColumnsADT t
128+ , G.GColumnsADT TColumns (GRep t (Reify Name)) ~ GColumnsADT t
129+ , Functor (GConstructors TUnreify (GRep t (Reify Expr)))
130+ , Functor (GConstructors TUnreify (GRep t (Reify Insert)))
131+ , HTable (G.GColumnsADT TColumns (GRep t (Reify Result)))
132+ , GConstructableADT (TTable (Reify Aggregate)) TColumns TUnreify (Col (Reify Aggregate)) (GRep t (Reify Aggregate))
133+ , GConstructableADT (TTable (Reify Expr)) TColumns TUnreify (Col (Reify Expr)) (GRep t (Reify Expr))
134+ , GConstructableADT (TTable (Reify Insert)) TColumns TUnreify (Col (Reify Insert)) (GRep t (Reify Insert))
135+ , GConstructableADT (TTable (Reify Name)) TColumns TUnreify (Col (Reify Name)) (GRep t (Reify Name))
137+ => ConstructableADT t
140+type ConstructADT :: K.Rel8able -> Type
141+type ConstructADT t = (forall r. GConstructADT TUnreify (GRep t (Reify Expr)) r r) -> ADT t Expr
144+constructADT :: forall t. ConstructableADT t => ConstructADT t
146+ gcindex @TUnreify @(GRep t (Reify Expr)) @(ADT t Expr) (f @(ADT t Expr)) $
147+ fmap (ADT . hunreify) $
149+ @(TTable (Reify Expr))
153+ @(GRep t (Reify Expr))
154+ (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
155+ (\SSpec {info} -> Reify (DB (snull info)))
156+ (\SSpec {nullity} -> case nullity of
158+ NotNull -> \(Reify (DB a)) -> Reify (DB (nullify a)))
159+ (HType . Reify . DB . litExpr)
162+type DeconstructADT :: K.Rel8able -> Type -> Type
163+type DeconstructADT t r = GConstructADT TUnreify (GRep t (Reify Expr)) r (ADT t Expr -> r)
166+deconstructADT :: forall t r. (ConstructableADT t, Table Expr r)
167+ => DeconstructADT t r
169+ gctabulate @TUnreify @(GRep t (Reify Expr)) @r @(ADT t Expr -> r)
170+ \constructors (ADT columns) ->
172+ (HType (Reify (DB tag)), cases) = gdeconstructADT
173+ @(TTable (Reify Expr))
177+ @(GRep t (Reify Expr))
178+ (\(_ :: proxy x) -> unreify @_ @x Refl . fromColumns)
179+ (\SSpec {nullity} -> case nullity of
181+ NotNull -> \(Reify (DB a)) -> Reify (DB (unsafeUnnullify a)))
186+ ((_, r) :| (map (first ((tag ==.) . litExpr)) -> cases')) ->
190+type InsertADT :: K.Rel8able -> Type
191+type InsertADT t = (forall r. GConstructADT TUnreify (GRep t (Reify Insert)) r r) -> ADT t Insert
194+insertADT :: forall t. ConstructableADT t => InsertADT t
196+ gcindex @TUnreify @(GRep t (Reify Insert)) @(ADT t Insert) (f @(ADT t Insert)) $
197+ fmap (ADT . hunreify) $
199+ @(TTable (Reify Insert))
202+ @(Col (Reify Insert))
203+ @(GRep t (Reify Insert))
204+ (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
205+ (\SSpec {necessity, info} -> Reify $ case necessity of
206+ SRequired -> RequiredInsert (snull info)
207+ SOptional -> OptionalInsert (Just (snull info)))
208+ (\SSpec {nullity} -> case nullity of
211+ Reify (RequiredInsert a) -> Reify (RequiredInsert (nullify a))
212+ Reify (OptionalInsert a) -> Reify (OptionalInsert (nullify <$> a)))
213+ (HType . Reify . RequiredInsert . litExpr)
216+type NameADT :: K.Rel8able -> Type
217+type NameADT t = Name Tag -> GBuildADT TUnreify (GRep t (Reify Name)) (ADT t Name)
220+nameADT :: forall t. ConstructableADT t => NameADT t
221+nameADT tag = gftabulate @TUnreify @(GRep t (Reify Name)) @(ADT t Name) $
225+ @(TTable (Reify Name))
229+ @(GRep t (Reify Name))
230+ (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
231+ (\_ _ (Reify (NameCol a)) -> Reify (NameCol a))
232+ (HType ((\(Name a) -> Reify (NameCol a)) tag))
235+type AggregateADT :: K.Rel8able -> Type
236+type AggregateADT t = forall r.
237+ GBuildADT TUnreify (GRep t (Reify Expr))
238+ (GBuildADT TUnreify (GRep t (Reify Aggregate)) r -> r)
241+aggregateADT :: forall t. ConstructableADT t
242+ => AggregateADT t -> ADT t Expr -> ADT t Aggregate
243+aggregateADT builder (ADT columns) = f exprs $
247+ @(TTable (Reify Aggregate))
250+ @(Col (Reify Aggregate))
251+ @(GRep t (Reify Aggregate))
252+ (\(_ :: proxy x) -> toColumns . reify @_ @x Refl)
253+ (\tag' SSpec {nullity} (Reify (Aggregation aggregate)) ->
255+ condition = tag ==. litExpr tag'
259+ mapInputs (toPrimExpr . runTag nullity condition . fromPrimExpr) $
260+ runTag nullity condition <$> aggregate)
261+ (HType (Reify (Aggregation (groupByExpr tag))))
266+ @(GRep t (Reify Expr))
267+ @(GBuildADT TUnreify (GRep t (Reify Aggregate)) (ADT t Aggregate) -> ADT t Aggregate)
268+ (builder @(ADT t Aggregate))
272+ @(GRep t (Reify Aggregate))
274+ (HType (Reify (DB tag)), exprs) =
276+ @(TTable (Reify Expr))
280+ @(GRep t (Reify Expr))
281+ (\(_ :: proxy x) -> unreify @_ @x Refl . fromColumns)
282+ (\SSpec {nullity} -> case nullity of
284+ NotNull -> \(Reify (DB a)) -> Reify (DB (unsafeUnnullify a)))