on master help sign in
Eliminate the need for Array1D (i.e., unify with [])
4475085Shane O'Brien
rel8.cabal−1
@@ -168,7 +168,6 @@ library
168
168
169 Rel8.Type
169 Rel8.Type
170 Rel8.Type.Array
170 Rel8.Type.Array
171− Rel8.Type.Array1D
172 Rel8.Type.Composite
171 Rel8.Type.Composite
173 Rel8.Type.Eq
172 Rel8.Type.Eq
174 Rel8.Type.Enum
173 Rel8.Type.Enum
src/Rel8.hs−4
@@ -218,7 +218,6 @@ module Rel8
218 , countRows
218 , countRows
219 , groupBy
219 , groupBy
220 , headAgg
220 , headAgg
221− , array1DAggExpr
222 , listAgg, listAggExpr
221 , listAgg, listAggExpr
223 , nonEmptyAgg, nonEmptyAggExpr
222 , nonEmptyAgg, nonEmptyAggExpr
224 , DBMax, max
223 , DBMax, max
@@ -272,8 +271,6 @@ module Rel8
272 -- TODO
271 -- TODO
273 -- These need organizing, but are reachable from Rel8's documentation so we
272 -- These need organizing, but are reachable from Rel8's documentation so we
274 -- do need to export and document them.
273 -- do need to export and document them.
275− , Array1D( Array1D )
276− , NotArray
277 , Nullable
274 , Nullable
278 , NotNull
275 , NotNull
279 , HTable
276 , HTable
@@ -358,7 +355,6 @@ import Rel8.Table.Rel8able ()
358import Rel8.Table.Serialize
355import Rel8.Table.Serialize
359import Rel8.Table.These
356import Rel8.Table.These
360import Rel8.Type
357import Rel8.Type
361−import Rel8.Type.Array1D
362import Rel8.Type.Composite
358import Rel8.Type.Composite
363import Rel8.Type.Eq
359import Rel8.Type.Eq
364import Rel8.Type.Enum
360import Rel8.Type.Enum
src/Rel8/Aggregate/Legacy.hs+6−3
@@ -1,6 +1,7 @@
1{-# language AllowAmbiguousTypes #-}
1{-# language AllowAmbiguousTypes #-}
2{-# language DataKinds #-}
2{-# language DataKinds #-}
3{-# language FlexibleContexts #-}
3{-# language FlexibleContexts #-}
4+{-# language NamedFieldPuns #-}
4{-# language RankNTypes #-}
5{-# language RankNTypes #-}
5{-# language ScopedTypeVariables #-}
6{-# language ScopedTypeVariables #-}
6{-# language StandaloneKindSignatures #-}
7{-# language StandaloneKindSignatures #-}
@@ -37,7 +38,8 @@ import Rel8.Expr ( Col( E ), Expr )
37import Rel8.Expr.Aggregate
38import Rel8.Expr.Aggregate
38 ( groupByExpr
39 ( groupByExpr
39 , headAggExpr
40 , headAggExpr
40− , listAggExpr, nonEmptyAggExpr
41+ , slistAggExpr
42+ , snonEmptyAggExpr
41 )
43 )
42import Rel8.Generic.Construction ( GGAggregate', ggaggregate' )
44import Rel8.Generic.Construction ( GGAggregate', ggaggregate' )
43import Rel8.Generic.Table ( GAlgebra )
45import Rel8.Generic.Table ( GAlgebra )
@@ -48,6 +50,7 @@ import Rel8.Schema.Dict ( Dict( Dict ) )
48import Rel8.Schema.HTable ( hmap, hfield, htabulate )
50import Rel8.Schema.HTable ( hmap, hfield, htabulate )
49import Rel8.Schema.HTable.Vectorize ( hvectorize )
51import Rel8.Schema.HTable.Vectorize ( hvectorize )
50import Rel8.Schema.Kind ( Rel8able )
52import Rel8.Schema.Kind ( Rel8able )
53+import Rel8.Schema.Spec ( SSpec( SSpec, info ) )
51import Rel8.Table ( toColumns, fromColumns )
54import Rel8.Table ( toColumns, fromColumns )
52import Rel8.Table.ADT ( ConstructableADT, ADT( ADT ), ADTRep )
55import Rel8.Table.ADT ( ConstructableADT, ADT( ADT ), ADTRep )
53import Rel8.Table.Eq ( EqTable, eqTable )
56import Rel8.Table.Eq ( EqTable, eqTable )
@@ -105,7 +108,7 @@ headAgg = fromColumns . hmap (\(E a) -> A $ headAggExpr a) . toColumns
105listAgg :: Aggregates aggregates exprs => exprs -> ListTable aggregates
108listAgg :: Aggregates aggregates exprs => exprs -> ListTable aggregates
106listAgg (toColumns -> exprs) = fromColumns $
109listAgg (toColumns -> exprs) = fromColumns $
107 hvectorize
110 hvectorize
108− (\_ (Identity (E a)) -> A $ listAggExpr a)
111+ (\SSpec {info} (Identity (E a)) -> A $ slistAggExpr info a)
109 (pure exprs)
112 (pure exprs)
110
113
111
114
@@ -113,7 +116,7 @@ listAgg (toColumns -> exprs) = fromColumns $
113nonEmptyAgg :: Aggregates aggregates exprs => exprs -> NonEmptyTable aggregates
116nonEmptyAgg :: Aggregates aggregates exprs => exprs -> NonEmptyTable aggregates
114nonEmptyAgg (toColumns -> exprs) = fromColumns $
117nonEmptyAgg (toColumns -> exprs) = fromColumns $
115 hvectorize
118 hvectorize
116− (\_ (Identity (E a)) -> A $ nonEmptyAggExpr a)
119+ (\SSpec {info} (Identity (E a)) -> A $ snonEmptyAggExpr info a)
117 (pure exprs)
120 (pure exprs)
118
121
119
122
src/Rel8/Expr/Aggregate.hs+22−20
@@ -13,7 +13,8 @@ module Rel8.Expr.Aggregate
13 , stringAgg
13 , stringAgg
14 , groupByExpr
14 , groupByExpr
15 , headAggExpr
15 , headAggExpr
16− , array1DAggExpr, listAggExpr, nonEmptyAggExpr
16+ , listAggExpr, nonEmptyAggExpr
17+ , slistAggExpr, snonEmptyAggExpr
17 )
18 )
18where
19where
19
20
@@ -37,10 +38,11 @@ import Rel8.Expr.Opaleye
37 )
38 )
38import Rel8.Expr.Null ( null )
39import Rel8.Expr.Null ( null )
39import Rel8.Expr.Serialize ( litExpr )
40import Rel8.Expr.Serialize ( litExpr )
40−import Rel8.Schema.Null ( Sql )
41+import Rel8.Schema.Null ( Sql, Unnullify )
42+import Rel8.Type ( DBType, typeInformation )
41−import Rel8.Type.Array ( fromPrimArray )
43+import Rel8.Type.Array ( wrap )
42−import Rel8.Type.Array1D ( Array1D, NotArray )
43import Rel8.Type.Eq ( DBEq )
44import Rel8.Type.Eq ( DBEq )
45+import Rel8.Type.Information ( TypeInformation )
44import Rel8.Type.Num ( DBNum )
46import Rel8.Type.Num ( DBNum )
45import Rel8.Type.Ord ( DBMax, DBMin )
47import Rel8.Type.Ord ( DBMax, DBMin )
46import Rel8.Type.String ( DBString )
48import Rel8.Type.String ( DBString )
@@ -168,35 +170,35 @@ headAggExpr = unsafeMakeAggregate toPrimExpr from $ Just
168 one = Opaleye.ConstExpr (Opaleye.NumericLit 1)
170 one = Opaleye.ConstExpr (Opaleye.NumericLit 1)
169
171
170
172
171−-- | Collect expressions values as an array.
173+-- | Collect expressions values as a list.
172−array1DAggExpr :: NotArray a => Expr a -> Aggregate (Expr (Array1D a))
174+listAggExpr :: Sql DBType a => Expr a -> Aggregate (Expr [a])
173−array1DAggExpr = unsafeMakeAggregate toPrimExpr fromPrimExpr $ Just
175+listAggExpr = slistAggExpr typeInformation
174− Aggregator
175− { operation = Opaleye.AggrArr
176− , ordering = []
177− , distinction = Opaleye.AggrAll
178− }
179
176
180
177
181−-- | Collect expressions values as a list.
178+-- | Collect expressions values as a non-empty list.
179+nonEmptyAggExpr :: Sql DBType a => Expr a -> Aggregate (Expr (NonEmpty a))
180+nonEmptyAggExpr = snonEmptyAggExpr typeInformation
181+
182+
183+slistAggExpr :: ()
182−listAggExpr :: Expr a -> Aggregate (Expr [a])
184+ => TypeInformation (Unnullify a) -> Expr a -> Aggregate (Expr [a])
183−listAggExpr = unsafeMakeAggregate toPrimExpr from $ Just
185+slistAggExpr info = unsafeMakeAggregate to fromPrimExpr $ Just
184 Aggregator
186 Aggregator
185 { operation = Opaleye.AggrArr
187 { operation = Opaleye.AggrArr
186 , ordering = []
188 , ordering = []
187 , distinction = Opaleye.AggrAll
189 , distinction = Opaleye.AggrAll
188 }
190 }
189 where
191 where
190− from = fromPrimExpr . fromPrimArray
192+ to = wrap info . toPrimExpr
191
193
192
194
193−-- | Collect expressions values as a non-empty list.
195+snonEmptyAggExpr :: ()
194−nonEmptyAggExpr :: Expr a -> Aggregate (Expr (NonEmpty a))
196+ => TypeInformation (Unnullify a) -> Expr a -> Aggregate (Expr (NonEmpty a))
195−nonEmptyAggExpr = unsafeMakeAggregate toPrimExpr from $ Just
197+snonEmptyAggExpr info = unsafeMakeAggregate to fromPrimExpr $ Just
196 Aggregator
198 Aggregator
197 { operation = Opaleye.AggrArr
199 { operation = Opaleye.AggrArr
198 , ordering = []
200 , ordering = []
199 , distinction = Opaleye.AggrAll
201 , distinction = Opaleye.AggrAll
200 }
202 }
201 where
203 where
202− from = fromPrimExpr . fromPrimArray
204+ to = wrap info . toPrimExpr
src/Rel8/Expr/Array.hs+6−6
@@ -25,21 +25,21 @@ import Rel8.Expr.Opaleye
25 , zipPrimExprsWith
25 , zipPrimExprsWith
26 )
26 )
27import Rel8.Type ( DBType, typeInformation )
27import Rel8.Type ( DBType, typeInformation )
28−import Rel8.Type.Array ( array, zipPrimArraysWith )
28+import Rel8.Type.Array ( array )
29import Rel8.Type.Information ( TypeInformation(..) )
29import Rel8.Type.Information ( TypeInformation(..) )
30−import Rel8.Schema.Null ( Unnullify, Nullity, Sql )
30+import Rel8.Schema.Null ( Unnullify, Sql )
31
31
32
32
33sappend :: Expr [a] -> Expr [a] -> Expr [a]
33sappend :: Expr [a] -> Expr [a] -> Expr [a]
34−sappend = zipPrimExprsWith (zipPrimArraysWith (Opaleye.BinExpr (Opaleye.:||)))
34+sappend = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:||))
35
35
36
36
37sappend1 :: Expr (NonEmpty a) -> Expr (NonEmpty a) -> Expr (NonEmpty a)
37sappend1 :: Expr (NonEmpty a) -> Expr (NonEmpty a) -> Expr (NonEmpty a)
38−sappend1 = zipPrimExprsWith (zipPrimArraysWith (Opaleye.BinExpr (Opaleye.:||)))
38+sappend1 = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:||))
39
39
40
40
41−sempty :: Nullity a -> TypeInformation (Unnullify a) -> Expr [a]
41+sempty :: TypeInformation (Unnullify a) -> Expr [a]
42−sempty _ info = fromPrimExpr $ array info []
42+sempty info = fromPrimExpr $ array info []
43
43
44
44
45slistOf :: TypeInformation (Unnullify a) -> [Expr a] -> Expr [a]
45slistOf :: TypeInformation (Unnullify a) -> [Expr a] -> Expr [a]
src/Rel8/Expr/Text.hs+1−2
@@ -32,7 +32,6 @@ import Data.ByteString ( ByteString )
32-- rel8
32-- rel8
33import Rel8.Expr ( Expr )
33import Rel8.Expr ( Expr )
34import Rel8.Expr.Function ( binaryOperator, function, nullaryFunction )
34import Rel8.Expr.Function ( binaryOperator, function, nullaryFunction )
35−import Rel8.Type.Array1D ( Array1D )
36
35
37-- text
36-- text
38import Data.Text (Text)
37import Data.Text (Text)
@@ -218,7 +217,7 @@ regexpReplace a b c Nothing = function "regexp_replace" a b c
218
217
219-- | Corresponds to the @regexp_split_to_array@ function.
218-- | Corresponds to the @regexp_split_to_array@ function.
220regexpSplitToArray :: ()
219regexpSplitToArray :: ()
221− => Expr Text -> Expr Text -> Maybe (Expr Text) -> Expr (Array1D Text)
220+ => Expr Text -> Expr Text -> Maybe (Expr Text) -> Expr [Text]
222regexpSplitToArray a b (Just c) = function "regexp_split_to_array" a b c
221regexpSplitToArray a b (Just c) = function "regexp_split_to_array" a b c
223regexpSplitToArray a b Nothing = function "regexp_split_to_array" a b
222regexpSplitToArray a b Nothing = function "regexp_split_to_array" a b
224
223
src/Rel8/Query/List.hs+1−1
@@ -55,5 +55,5 @@ manyExpr = fmap (maybeTable mempty id) . optional . aggregate . fmap listAggExpr
55
55
56
56
57-- | A version of 'many' specialised to single expressions.
57-- | A version of 'many' specialised to single expressions.
58−someExpr :: Query (Expr a) -> Query (Expr (NonEmpty a))
58+someExpr :: Sql DBType a => Query (Expr a) -> Query (Expr (NonEmpty a))
59someExpr = aggregate . fmap nonEmptyAggExpr
59someExpr = aggregate . fmap nonEmptyAggExpr
src/Rel8/Table/Aggregate.hs+6−4
@@ -1,4 +1,5 @@
1{-# language FlexibleContexts #-}
1{-# language FlexibleContexts #-}
2+{-# language NamedFieldPuns #-}
2{-# language ScopedTypeVariables #-}
3{-# language ScopedTypeVariables #-}
3{-# language TypeApplications #-}
4{-# language TypeApplications #-}
4{-# language TypeFamilies #-}
5{-# language TypeFamilies #-}
@@ -21,12 +22,13 @@ import Rel8.Expr ( Expr, Col( E ) )
21import Rel8.Expr.Aggregate
22import Rel8.Expr.Aggregate
22 ( groupByExpr
23 ( groupByExpr
23 , headAggExpr
24 , headAggExpr
24− , listAggExpr
25+ , slistAggExpr
25− , nonEmptyAggExpr
26+ , snonEmptyAggExpr
26 )
27 )
27import Rel8.Schema.Dict ( Dict( Dict ) )
28import Rel8.Schema.Dict ( Dict( Dict ) )
28import Rel8.Schema.HTable ( hfield, hmap, htabulate )
29import Rel8.Schema.HTable ( hfield, hmap, htabulate )
29import Rel8.Schema.HTable.Vectorize ( hvectorize )
30import Rel8.Schema.HTable.Vectorize ( hvectorize )
31+import Rel8.Schema.Spec ( SSpec( SSpec, info ) )
30import Rel8.Table ( Table, toColumns, fromColumns )
32import Rel8.Table ( Table, toColumns, fromColumns )
31import Rel8.Table.Eq ( EqTable, eqTable )
33import Rel8.Table.Eq ( EqTable, eqTable )
32import Rel8.Table.List ( ListTable )
34import Rel8.Table.List ( ListTable )
@@ -66,7 +68,7 @@ headAgg = fromColumns . hmap (\(E a) -> A $ headAggExpr a) . toColumns
66listAgg :: Table Expr a => a -> Aggregate (ListTable a)
68listAgg :: Table Expr a => a -> Aggregate (ListTable a)
67listAgg (toColumns -> exprs) = fromColumns $
69listAgg (toColumns -> exprs) = fromColumns $
68 hvectorize
70 hvectorize
69− (\_ (Identity (E a)) -> A $ listAggExpr a)
71+ (\SSpec {info} (Identity (E a)) -> A $ slistAggExpr info a)
70 (pure exprs)
72 (pure exprs)
71
73
72
74
@@ -74,5 +76,5 @@ listAgg (toColumns -> exprs) = fromColumns $
74nonEmptyAgg :: Table Expr a => a -> Aggregate (NonEmptyTable a)
76nonEmptyAgg :: Table Expr a => a -> Aggregate (NonEmptyTable a)
75nonEmptyAgg (toColumns -> exprs) = fromColumns $
77nonEmptyAgg (toColumns -> exprs) = fromColumns $
76 hvectorize
78 hvectorize
77− (\_ (Identity (E a)) -> A $ nonEmptyAggExpr a)
79+ (\SSpec {info} (Identity (E a)) -> A $ snonEmptyAggExpr info a)
78 (pure exprs)
80 (pure exprs)
src/Rel8/Table/List.hs+1−2
@@ -116,8 +116,7 @@ instance Table Expr a => Semigroup (ListTable a) where
116
116
117
117
118instance Table Expr a => Monoid (ListTable a) where
118instance Table Expr a => Monoid (ListTable a) where
119− mempty = ListTable $ hempty $ \nullability info ->
119+ mempty = ListTable $ hempty $ \_ -> E . sempty
120− E (sempty nullability info)
121
120
122
121
123listTable :: Table Expr a => [a] -> ListTable a
122listTable :: Table Expr a => [a] -> ListTable a
src/Rel8/Type/Array.hs+34−26
@@ -1,12 +1,13 @@
1{-# language GADTs #-}
1{-# language GADTs #-}
2+{-# language LambdaCase #-}
2{-# language NamedFieldPuns #-}
3{-# language NamedFieldPuns #-}
3{-# language OverloadedStrings #-}
4{-# language OverloadedStrings #-}
5+{-# language ViewPatterns #-}
4
6
5module Rel8.Type.Array
7module Rel8.Type.Array
6− ( array
8+ ( array, wrap
7 , listTypeInformation
9 , listTypeInformation
8 , nonEmptyTypeInformation
10 , nonEmptyTypeInformation
9− , fromPrimArray, toPrimArray, zipPrimArraysWith
10 )
11 )
11where
12where
12
13
@@ -28,10 +29,9 @@ import Rel8.Type.Information ( TypeInformation(..), parseTypeInformation )
28
29
29array :: Foldable f
30array :: Foldable f
30 => TypeInformation a -> f Opaleye.PrimExpr -> Opaleye.PrimExpr
31 => TypeInformation a -> f Opaleye.PrimExpr -> Opaleye.PrimExpr
31−array TypeInformation {typeName} =
32+array info =
32− fromPrimArray .
33− Opaleye.CastExpr (typeName <> "[]") .
33+ Opaleye.CastExpr (arrayType info <> "[]") .
34− Opaleye.ArrayExpr . toList
34+ Opaleye.ArrayExpr . map (wrap info) . toList
35{-# INLINABLE array #-}
35{-# INLINABLE array #-}
36
36
37
37
@@ -39,19 +39,17 @@ listTypeInformation :: ()
39 => Nullity a
39 => Nullity a
40 -> TypeInformation (Unnullify a)
40 -> TypeInformation (Unnullify a)
41 -> TypeInformation [a]
41 -> TypeInformation [a]
42−listTypeInformation nullity info =
42+listTypeInformation nullity info@TypeInformation {encode, decode} =
43− case info of
44− TypeInformation{ encode, decode } -> TypeInformation
43+ TypeInformation
45− { decode = row $ case nullity of
44+ { decode = case nullity of
46− Null -> Hasql.listArray (Hasql.nullable decode)
45+ Null -> Hasql.listArray (Hasql.nullable (unwrap info decode))
47− NotNull -> Hasql.listArray (Hasql.nonNullable decode)
46+ NotNull -> Hasql.listArray (Hasql.nonNullable (unwrap info decode))
48− , encode = case nullity of
47+ , encode = case nullity of
49− Null -> array info . fmap (maybe null encode)
48+ Null -> Opaleye.ArrayExpr . fmap (wrap info . maybe null encode)
50− NotNull -> array info . fmap encode
49+ NotNull -> Opaleye.ArrayExpr . fmap (wrap info . encode)
51− , typeName = "record"
50+ , typeName = arrayType info <> "[]"
52− }
51+ }
53 where
52 where
54− row = Hasql.composite . Hasql.field . Hasql.nonNullable
55 null = Opaleye.ConstExpr Opaleye.NullLit
53 null = Opaleye.ConstExpr Opaleye.NullLit
56
54
57
55
@@ -66,15 +64,25 @@ nonEmptyTypeInformation nullity =
66 message = "failed to decode NonEmptyList: got empty list"
64 message = "failed to decode NonEmptyList: got empty list"
67
65
68
66
69−fromPrimArray :: Opaleye.PrimExpr -> Opaleye.PrimExpr
67+isArray :: TypeInformation a -> Bool
70−fromPrimArray = Opaleye.UnExpr (Opaleye.UnOpOther "ROW")
68+isArray = \case
69+ (reverse . typeName -> ']' : '[' : _) -> True
70+ _ -> False
71
71
72
72
73−toPrimArray :: Opaleye.PrimExpr -> Opaleye.PrimExpr
73+arrayType :: TypeInformation a -> String
74−toPrimArray a = Opaleye.CompositeExpr a "f1"
74+arrayType info
75+ | isArray info = "record"
76+ | otherwise = typeName info
75
77
76
78
77−zipPrimArraysWith :: ()
78− => (Opaleye.PrimExpr -> Opaleye.PrimExpr -> Opaleye.PrimExpr)
79+wrap :: TypeInformation a -> Opaleye.PrimExpr -> Opaleye.PrimExpr
79− -> Opaleye.PrimExpr -> Opaleye.PrimExpr -> Opaleye.PrimExpr
80+wrap info
80−zipPrimArraysWith f a b = fromPrimArray (f (toPrimArray a) (toPrimArray b))
81+ | isArray info = Opaleye.UnExpr (Opaleye.UnOpOther "ROW")
82+ | otherwise = id
83+
84+
85+unwrap :: TypeInformation a -> Hasql.Value x -> Hasql.Value x
86+unwrap info
87+ | isArray info = Hasql.composite . Hasql.field . Hasql.nonNullable
88+ | otherwise = id
src/Rel8/Type/Array1D.hsdeleted−139
@@ -1,139 +0,0 @@
1−{-# language DataKinds #-}
2−{-# language DeriveTraversable #-}
3−{-# language DerivingStrategies #-}
4−{-# language FlexibleContexts #-}
5−{-# language FlexibleInstances #-}
6−{-# language GeneralizedNewtypeDeriving #-}
7−{-# language NamedFieldPuns #-}
8−{-# language StandaloneKindSignatures #-}
9−{-# language TypeFamilies #-}
10−{-# language UndecidableInstances #-}
11−
12−{-# options_ghc -fno-warn-redundant-constraints #-}
13−
14−module Rel8.Type.Array1D
15− ( Array1D( Array1D )
16− , NotArray
17− , getArray1D
18− )
19−where
20−
21−-- aeson
22−import Data.Aeson
23− ( ToJSON
24− , ToJSON1
25− , ToJSONKey
26− , FromJSON
27− , FromJSON1
28− , FromJSONKey
29− )
30−
31−-- base
32−import Control.Applicative ( Alternative, (<|>) )
33−import Control.Monad ( MonadPlus )
34−import Data.Functor.Classes ( Eq1, Ord1, Read1, Show1 )
35−import Data.Kind ( Type )
36−import GHC.Exts ( IsList )
37−import Prelude hiding ( null )
38−
39−-- hasql
40−import qualified Hasql.Decoders as Hasql
41−
42−-- opaleye
43−import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
44−
45−-- rel8
46−import Rel8.Expr.Opaleye ( zipPrimExprsWith )
47−import Rel8.Expr.Serialize ( litExpr )
48−import Rel8.Schema.Null ( Unnullify, Nullity( Null, NotNull ), Sql, nullable )
49−import Rel8.Type ( DBType, typeInformation )
50−import Rel8.Type.Eq ( DBEq )
51−import Rel8.Type.Information ( TypeInformation(..) )
52−import Rel8.Type.Monoid ( DBMonoid, memptyExpr )
53−import Rel8.Type.Ord ( DBMax, DBMin, DBOrd )
54−import Rel8.Type.Semigroup ( DBSemigroup, (<>.) )
55−
56−-- semigroupoids
57−import Data.Functor.Alt ( Alt, (<!>) )
58−import Data.Functor.Apply ( Apply )
59−import Data.Functor.Bind ( Bind )
60−import Data.Functor.Plus ( Plus )
61−
62−-- semialign
63−import Data.Align ( Align )
64−import Data.Semialign ( Semialign )
65−import Data.Zip ( Repeat, Unzip, Zip )
66−
67−
68−-- | A one dimensional array.
69−newtype Array1D a = Array1D [a]
70− deriving stock Traversable
71− deriving newtype
72− ( Eq, Ord, Read, Show, Semigroup, Monoid, IsList
73− , Functor, Foldable
74− , Eq1, Ord1, Read1, Show1
75− , FromJSON1, ToJSON1, FromJSON, FromJSONKey, ToJSON, ToJSONKey
76− , Apply, Applicative, Alternative, Plus, Bind, Monad, MonadPlus
77− , Align, Semialign, Repeat, Unzip, Zip
78− )
79−
80−
81−instance Alt Array1D where
82− (<!>) = (<|>)
83−
84−
85−getArray1D :: Array1D a -> [a]
86−getArray1D (Array1D a) = a
87−
88−
89−type IsArray1D :: Type -> Bool
90−type family IsArray1D a where
91− IsArray1D (Array1D _) = 'True
92− IsArray1D _ = 'False
93−
94−
95−class IsArray1D a ~ 'False => NotArray a
96−instance IsArray1D a ~ 'False => NotArray a
97−
98−
99−array1DTypeInformation :: Sql NotArray a
100− => Nullity a
101− -> TypeInformation (Unnullify a)
102− -> TypeInformation (Array1D a)
103−array1DTypeInformation nullity info =
104− case info of
105− TypeInformation{ encode, decode, typeName } -> TypeInformation
106− { decode = case nullity of
107− Null -> Array1D <$> Hasql.listArray (Hasql.nullable decode)
108− NotNull -> Array1D <$> Hasql.listArray (Hasql.nonNullable decode)
109− , encode = case nullity of
110− Null -> Opaleye.ArrayExpr . fmap (maybe null encode) . getArray1D
111− NotNull -> Opaleye.ArrayExpr . fmap encode . getArray1D
112− , typeName = typeName <> "[]"
113− }
114− where
115− null = Opaleye.ConstExpr Opaleye.NullLit
116−
117−
118−instance (Sql DBType a, Sql NotArray a) => DBType (Array1D a) where
119− typeInformation = array1DTypeInformation nullable typeInformation
120−
121−
122−instance (Sql DBEq a, Sql NotArray a) => DBEq (Array1D a)
123−
124−
125−instance (Sql DBOrd a, Sql NotArray a) => DBOrd (Array1D a)
126−
127−
128−instance (Sql DBMax a, Sql NotArray a) => DBMax (Array1D a)
129−
130−
131−instance (Sql DBMin a, Sql NotArray a) => DBMin (Array1D a)
132−
133−
134−instance (Sql DBType a, Sql NotArray a) => DBSemigroup (Array1D a) where
135− (<>.) = zipPrimExprsWith (Opaleye.BinExpr (Opaleye.:||))
136−
137−
138−instance (Sql DBType a, Sql NotArray a) => DBMonoid (Array1D a) where
139− memptyExpr = litExpr mempty
src/Rel8/Type/Monoid.hs+2−2
@@ -27,7 +27,7 @@ import Data.CaseInsensitive ( CI )
27import {-# SOURCE #-} Rel8.Expr ( Expr )
27import {-# SOURCE #-} Rel8.Expr ( Expr )
28import Rel8.Expr.Array ( sempty )
28import Rel8.Expr.Array ( sempty )
29import Rel8.Expr.Serialize ( litExpr )
29import Rel8.Expr.Serialize ( litExpr )
30−import Rel8.Schema.Null ( Sql, nullable )
30+import Rel8.Schema.Null ( Sql )
31import Rel8.Type ( DBType, typeInformation )
31import Rel8.Type ( DBType, typeInformation )
32import Rel8.Type.Semigroup ( DBSemigroup )
32import Rel8.Type.Semigroup ( DBSemigroup )
33
33
@@ -48,7 +48,7 @@ class DBSemigroup a => DBMonoid a where
48
48
49
49
50instance Sql DBType a => DBMonoid [a] where
50instance Sql DBType a => DBMonoid [a] where
51− memptyExpr = sempty nullable typeInformation
51+ memptyExpr = sempty typeInformation
52
52
53
53
54instance DBMonoid CalendarDiffTime where
54instance DBMonoid CalendarDiffTime where
src/Rel8/Type/Semigroup.hs+4−7
@@ -13,10 +13,9 @@ module Rel8.Type.Semigroup
13where
13where
14
14
15-- base
15-- base
16−import Data.Function ( on )
17import Data.Kind ( Constraint, Type )
16import Data.Kind ( Constraint, Type )
18import Data.List.NonEmpty ( NonEmpty )
17import Data.List.NonEmpty ( NonEmpty )
19−import Prelude
18+import Prelude ()
20
19
21-- bytestring
20-- bytestring
22import Data.ByteString ( ByteString )
21import Data.ByteString ( ByteString )
@@ -30,10 +29,10 @@ import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
30
29
31-- rel8
30-- rel8
32import {-# SOURCE #-} Rel8.Expr ( Expr )
31import {-# SOURCE #-} Rel8.Expr ( Expr )
32+import Rel8.Expr.Array ( sappend, sappend1 )
33import Rel8.Expr.Opaleye ( zipPrimExprsWith )
33import Rel8.Expr.Opaleye ( zipPrimExprsWith )
34import Rel8.Schema.Null ( Sql )
34import Rel8.Schema.Null ( Sql )
35import Rel8.Type ( DBType )
35import Rel8.Type ( DBType )
36−import Rel8.Type.Array ( fromPrimArray, toPrimArray )
37
36
38-- text
37-- text
39import Data.Text ( Text )
38import Data.Text ( Text )
@@ -53,13 +52,11 @@ class DBType a => DBSemigroup a where
53
52
54
53
55instance Sql DBType a => DBSemigroup [a] where
54instance Sql DBType a => DBSemigroup [a] where
56− (<>.) = zipPrimExprsWith do
55+ (<>.) = sappend
57− (fromPrimArray .) . Opaleye.BinExpr (Opaleye.:||) `on` toPrimArray
58
56
59
57
60instance Sql DBType a => DBSemigroup (NonEmpty a) where
58instance Sql DBType a => DBSemigroup (NonEmpty a) where
61− (<>.) = zipPrimExprsWith do
59+ (<>.) = sappend1
62− (fromPrimArray .) . Opaleye.BinExpr (Opaleye.:||) `on` toPrimArray
63
60
64
61
65instance DBSemigroup CalendarDiffTime where
62instance DBSemigroup CalendarDiffTime where