on dev help sign in
break off literals
commit4148e1ad829c9c6677e8ebd8ff8039bab11134ed authorEitan Chatav <eitan@Eitans-MacBook-Pro.local> dateFri 12 Apr 2019, 17:39 (8 years ago) parent64b6296
4 files changed+88−45
squeal-postgresql/squeal-postgresql.cabal+1 squeal-postgresql/src/Squeal/PostgreSQL.hs+2 squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+8−45 squeal-postgresql/src/Squeal/PostgreSQL/Expression/Literal.hs+77
squeal-postgresql/squeal-postgresql.cabal+1
@@ -30,6 +30,7 @@ library
3030 Squeal.PostgreSQL.Expression.Collection
3131 Squeal.PostgreSQL.Expression.Comparison
3232 Squeal.PostgreSQL.Expression.Json
33+ Squeal.PostgreSQL.Expression.Literal
3334 Squeal.PostgreSQL.Expression.Logic
3435 Squeal.PostgreSQL.Expression.Math
3536 Squeal.PostgreSQL.Expression.Null
squeal-postgresql/src/Squeal/PostgreSQL.hs+2
@@ -202,6 +202,7 @@ module Squeal.PostgreSQL
202202 , module Squeal.PostgreSQL.Expression.Collection
203203 , module Squeal.PostgreSQL.Expression.Comparison
204204 , module Squeal.PostgreSQL.Expression.Json
205+ , module Squeal.PostgreSQL.Expression.Literal
205206 , module Squeal.PostgreSQL.Expression.Logic
206207 , module Squeal.PostgreSQL.Expression.Math
207208 , module Squeal.PostgreSQL.Expression.Null
@@ -231,6 +232,7 @@ import Squeal.PostgreSQL.Expression.Aggregate
231232import Squeal.PostgreSQL.Expression.Collection
232233import Squeal.PostgreSQL.Expression.Comparison
233234import Squeal.PostgreSQL.Expression.Json
235+import Squeal.PostgreSQL.Expression.Literal
234236import Squeal.PostgreSQL.Expression.Logic
235237import Squeal.PostgreSQL.Expression.Math
236238import Squeal.PostgreSQL.Expression.Null
squeal-postgresql/src/Squeal/PostgreSQL/Expression.hs+8−45
@@ -45,39 +45,29 @@ module Squeal.PostgreSQL.Expression
4545 , unsafeFunctionVar
4646 , FunctionN
4747 , unsafeFunctionN
48− , Literal (..)
4948 , PGSubset (..)
5049 -- * Re-export
5150 , (&)
5251 , K (..)
52+ , unK
5353 ) where
5454
5555import Control.Category
5656import Control.DeepSeq
5757import Data.ByteString (ByteString)
58−import Data.ByteString.Lazy (toStrict)
59−import ByteString.StrictBuilder (builderBytes)
6058import Data.Function ((&))
6159import Data.Semigroup hiding (All)
62−import qualified Data.Aeson as JSON
63−import Data.Int
6460import Data.String
65−import Data.Text (Text)
6661import Generics.SOP hiding (All, from)
6762import GHC.OverloadedLabels
6863import GHC.TypeLits
6964import Numeric
7065import Prelude hiding (id, (.))
7166
72−import qualified Data.Text as Text
73−import qualified Data.Text.Lazy as Lazy (Text)
74−import qualified Data.Text.Lazy as Lazy.Text
7567import qualified GHC.Generics as GHC
7668
7769import Squeal.PostgreSQL.Alias
78−import Squeal.PostgreSQL.Binary
7970import Squeal.PostgreSQL.List
80−import Squeal.PostgreSQL.PG
8171import Squeal.PostgreSQL.Render
8272import Squeal.PostgreSQL.Schema
8373
@@ -93,7 +83,7 @@ such as in the target `Squeal.PostgreSQL.Query.List` of the
9383`Squeal.PostgreSQL.Query.select` command,
9484as new column values in `Squeal.PostgreSQL.Manipulation.insertRow` or
9585`Squeal.PostgreSQL.Manipulation.update`,
96−or in search `Condition`s in a number of commands.
86+or in search `Squeal.PostgreSQL.Logic.Condition`s in a number of commands.
9787
9888The expression syntax allows the calculation of
9989values from primitive expression using arithmetic, logical,
@@ -127,7 +117,7 @@ instance RenderSQL (Expression outer commons grp schemas params from ty) where
127117 renderSQL = renderExpression
128118
129119-- | An `Expr` is a closed `Expression`.
130−-- It is a F`RankNType` but don't be scared.
120+-- It is a F@RankNType@ but don't be scared.
131121-- Think of it as an expression which sees no
132122-- namespaces, so you can't use parameters
133123-- or alias references. It can be used as
@@ -137,7 +127,7 @@ type Expr x
137127 . Expression outer commons grp schemas params from x
138128 -- ^ cannot reference aliases
139129
140−-- | A `RankNType` for binary operators.
130+-- | A @RankNType@ for binary operators.
141131type Operator x1 x2 y
142132 = forall outer commons grp schemas params from
143133 . Expression outer commons grp schemas params from x1
@@ -147,7 +137,7 @@ type Operator x1 x2 y
147137 -> Expression outer commons grp schemas params from y
148138 -- ^ output
149139
150−-- | A `RankNType` for functions with a single argument.
140+-- | A @RankNType@ for functions with a single argument.
151141-- These could be either function calls or unary operators.
152142-- This is a subtype of the usual Haskell function type `Prelude.->`,
153143-- indeed a subcategory as it is closed under the usual
@@ -159,7 +149,7 @@ type (:-->) x y
159149 -> Expression outer commons grp schemas params from y
160150 -- ^ output
161151
162−{- | A `RankNType` for functions with a fixed-length list of heterogeneous arguments.
152+{- | A @RankNType@ for functions with a fixed-length list of heterogeneous arguments.
163153Use the `*:` operator to end your argument lists, like so.
164154
165155>>> printSQL (unsafeFunctionN "fun" (true :* false :* localTime *: true))
@@ -172,7 +162,7 @@ type FunctionN xs y
172162 -> Expression outer commons grp schemas params from y
173163 -- ^ output
174164
175−{- | A `RankNType` for functions with a variable-length list of
165+{- | A @RankNType@ for functions with a variable-length list of
176166homogeneous arguments and at least 1 more argument.
177167-}
178168type FunctionVar x0 x1 y
@@ -363,6 +353,7 @@ instance (ty `In` PGNum, ty `In` PGFloating) => Floating
363353 acosh x = log (x + sqrt (x*x - 1))
364354 atanh x = log ((1 + x) / (1 - x)) / 2
365355
356+-- | Contained by operators
366357class PGSubset container where
367358 (@>) :: Operator (null0 container) (null1 container) ('Null 'PGbool)
368359 (@>) = unsafeBinaryOp "@>"
@@ -406,31 +397,3 @@ instance Monoid
406397 (Expression outer commons grp schemas params from (null 'PGtsvector)) where
407398 mempty = fromString ""
408399 mappend = (<>)
409−
410−class Literal hask where
411− literal :: hask -> Expr (null (PG hask))
412−instance JSON.ToJSON hask => Literal (Json hask) where
413− literal = UnsafeExpression . parenthesized . (<> " :: json")
414− . singleQuotedUtf8 . toStrict . JSON.encode . getJson
415−instance JSON.ToJSON hask => Literal (Jsonb hask) where
416− literal = UnsafeExpression . parenthesized . (<> " :: jsonb")
417− . singleQuotedUtf8 . toStrict . JSON.encode . getJsonb
418−instance Literal Char where
419− literal chr = UnsafeExpression $
420− "E\'" <> fromString (escape chr) <> "\'"
421−instance Literal String where literal = fromString
422−instance Literal Int16 where literal = fromIntegral
423−instance Literal Int32 where literal = fromIntegral
424−instance Literal Int64 where literal = fromIntegral
425−instance Literal Float where literal = fromRational . toRational
426−instance Literal Double where literal = fromRational . toRational
427−instance Literal Text where literal = fromString . Text.unpack
428−instance Literal Lazy.Text where literal = fromString . Lazy.Text.unpack
429−instance ToParam (Enumerated enum) (PG (Enumerated enum))
430− => Literal (Enumerated enum) where
431− literal
432− = UnsafeExpression
433− . singleQuotedUtf8
434− . builderBytes
435− . unK
436− . toParam @(Enumerated enum) @(PG (Enumerated enum))
squeal-postgresql/src/Squeal/PostgreSQL/Expression/Literal.hsnew file+77
@@ -0,0 +1,77 @@
1+{-# LANGUAGE
2+ FlexibleContexts
3+ , FlexibleInstances
4+ , LambdaCase
5+ , OverloadedStrings
6+ , RankNTypes
7+ , ScopedTypeVariables
8+ , TypeApplications
9+ , TypeSynonymInstances
10+ , UndecidableInstances
11+#-}
12+
13+module Squeal.PostgreSQL.Expression.Literal (Literal (..)) where
14+
15+import ByteString.StrictBuilder (builderBytes)
16+import Data.ByteString.Lazy (toStrict)
17+import Data.Int
18+import Data.String
19+import Data.Text (Text)
20+
21+import qualified Data.Aeson as JSON
22+import qualified Data.Text as Text
23+import qualified Data.Text.Lazy as Lazy (Text)
24+import qualified Data.Text.Lazy as Lazy.Text
25+
26+import Squeal.PostgreSQL.Binary
27+import Squeal.PostgreSQL.Expression
28+import Squeal.PostgreSQL.Expression.Logic
29+import Squeal.PostgreSQL.PG
30+import Squeal.PostgreSQL.Render
31+
32+{- |
33+The `Literal` class allows embedding a Haskell value directly
34+as an `Expression` using `literal`.
35+
36+>>> printSQL (literal 'a')
37+E'a'
38+
39+>>> printSQL (literal (1 :: Double))
40+1.0
41+
42+>>> printSQL (literal (Json [1 :: Double, 2]))
43+('[1.0,2.0]' :: json)
44+
45+>>> printSQL (literal (Enumerated GT))
46+'GT'
47+-}
48+class Literal hask where literal :: hask -> Expr (null (PG hask))
49+instance Literal Bool where
50+ literal = \case
51+ True -> true
52+ False -> false
53+instance JSON.ToJSON hask => Literal (Json hask) where
54+ literal = UnsafeExpression . parenthesized . (<> " :: json")
55+ . singleQuotedUtf8 . toStrict . JSON.encode . getJson
56+instance JSON.ToJSON hask => Literal (Jsonb hask) where
57+ literal = UnsafeExpression . parenthesized . (<> " :: jsonb")
58+ . singleQuotedUtf8 . toStrict . JSON.encode . getJsonb
59+instance Literal Char where
60+ literal chr = UnsafeExpression $
61+ "E\'" <> fromString (escape chr) <> "\'"
62+instance Literal String where literal = fromString
63+instance Literal Int16 where literal = fromIntegral
64+instance Literal Int32 where literal = fromIntegral
65+instance Literal Int64 where literal = fromIntegral
66+instance Literal Float where literal = fromRational . toRational
67+instance Literal Double where literal = fromRational . toRational
68+instance Literal Text where literal = fromString . Text.unpack
69+instance Literal Lazy.Text where literal = fromString . Lazy.Text.unpack
70+instance ToParam (Enumerated enum) (PG (Enumerated enum))
71+ => Literal (Enumerated enum) where
72+ literal
73+ = UnsafeExpression
74+ . singleQuotedUtf8
75+ . builderBytes
76+ . unK
77+ . toParam @(Enumerated enum) @(PG (Enumerated enum))