@@ -0,0 +1,106 @@
2+Module: Squeal.PostgreSQL.Expression.Range
3+Description: range types and functions
4+Copyright: (c) Eitan Chatav, 2019
5+Maintainer: eitan@morphism.tech
6+Stability: experimental
8+Range types and functions
22+ , MultiParamTypeClasses
27+ , ScopedTypeVariables
31+ , UndecidableInstances
34+module Squeal.PostgreSQL.Expression.Range
37+ , (<=..<=), (<..<), (<=..<), (<..<=)
38+ , pattern HalfGT, pattern HalfGTE
39+ , pattern HalfLT, pattern HalfLTE
41+ , pattern Closed, pattern Open
46+import qualified GHC.Generics as GHC
47+import qualified Generics.SOP as SOP
49+import Squeal.PostgreSQL.Expression
50+import Squeal.PostgreSQL.PG
51+import Squeal.PostgreSQL.Render
52+import Squeal.PostgreSQL.Schema
55+-- >>> import Squeal.PostgreSQL
57+-- | >>> printSQL $ range (HalfGTE now)
59+-- >>> printSQL $ range (0 <..<= (pi & astype numeric))
60+-- (0, (pi() :: numeric)]
62+ :: Range (Expression outer commons grp schemas params from ('NotNull ty))
63+ -> Expression outer commons grp schemas params from (null ('PGrange ty))
64+range = UnsafeExpression . renderSQL
67+ { closedBound :: Bool
68+ , getBound :: Maybe x
70+ ( Eq, Ord, Show, Read, GHC.Generic
71+ , Functor, Foldable, Traversable )
72+ deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
73+pattern Closed, Open :: Maybe x -> Bound x
74+pattern Closed x = Bound True x
75+pattern Open x = Bound False x
79+ | NonEmpty (Bound x) (Bound x)
81+ ( Eq, Ord, Show, Read, GHC.Generic
82+ , Functor, Foldable, Traversable )
83+ deriving anyclass (SOP.Generic, SOP.HasDatatypeInfo)
84+type instance PG (Range x) = 'PGrange (PG x)
86+instance RenderSQL x => RenderSQL (Range x) where
89+ NonEmpty l u -> commaSeparated [renderLower l, renderUpper u]
91+ renderLower (Bound isClosed x) =
92+ bool "(" "[" isClosed <> maybe "" renderSQL x
93+ renderUpper (Bound isClosed x) =
94+ maybe "" renderSQL x <> bool ")" "]" isClosed
96+(<=..<=), (<..<), (<=..<), (<..<=) :: x -> x -> Range x
97+x <=..<= y = NonEmpty (Closed (Just x)) (Closed (Just y))
98+x <..< y = NonEmpty (Open (Just x)) (Open (Just y))
99+x <=..< y = NonEmpty (Closed (Just x)) (Open (Just y))
100+x <..<= y = NonEmpty (Open (Just x)) (Closed (Just y))
102+pattern HalfGT, HalfGTE, HalfLT, HalfLTE :: x -> Range x
103+pattern HalfGT x = NonEmpty (Open (Just x)) (Open Nothing)
104+pattern HalfGTE x = NonEmpty (Closed (Just x)) (Open Nothing)
105+pattern HalfLT x = NonEmpty (Open Nothing) (Open (Just x))
106+pattern HalfLTE x = NonEmpty (Open Nothing) (Closed (Just x))