@@ -7,6 +7,7 @@
7 , LambdaCase
7 , LambdaCase
8 , MagicHash
8 , MagicHash
9 , OverloadedStrings
9 , OverloadedStrings
10+ , ScopedTypeVariables
10 , TypeFamilies
11 , TypeFamilies
11 , TypeOperators
12 , TypeOperators
12 , UndecidableInstances
13 , UndecidableInstances
@@ -16,15 +17,17 @@ module Squeel.PostgreSQL.Statement where
17import Control.Category
18import Control.Category
18import Data.Boolean
19import Data.Boolean
20+import Data.Boolean.Numbers
19import Data.ByteString (ByteString)
21import Data.ByteString (ByteString)
20import Data.Maybe
22import Data.Maybe
21import Data.Monoid
23import Data.Monoid
22import Data.String
25import Data.String
23import Generics.SOP
26import Generics.SOP
24import GHC.Exts
27import GHC.Exts
25import GHC.OverloadedLabels
28import GHC.OverloadedLabels
26import GHC.TypeLits
29import GHC.TypeLits
27−import Prelude hiding (id,(.))
30+import Prelude hiding (id,(.),RealFrac(..))
29import qualified Data.ByteString as ByteString
32import qualified Data.ByteString as ByteString
@@ -124,13 +127,120 @@ unsafeFunction
124unsafeFunction fun x = UnsafeExpression $ mconcat
127unsafeFunction fun x = UnsafeExpression $ mconcat
125 [fun, "(", renderExpression x, ")"]
128 [fun, "(", renderExpression x, ")"]
127−instance PGNum ty => Num (Expression params tables ('Required (nullity ty))) where
131+ => Num (Expression params tables ('Required (nullity ty))) where
128− (+) = unsafeBinaryOp "+"
132+ (+) = unsafeBinaryOp "+"
129− (-) = unsafeBinaryOp "-"
133+ (-) = unsafeBinaryOp "-"
130− (*) = unsafeBinaryOp "*"
134+ (*) = unsafeBinaryOp "*"
131− abs = unsafeUnaryOp "@"
135+ abs = unsafeFunction "abs"
132− signum = unsafeFunction "sign"
136+ signum = unsafeFunction "sign"
133− fromInteger = UnsafeExpression . fromString . show
137+ fromInteger = UnsafeExpression . (<> ".") . fromString . show
139+instance PGFractional ty
140+ => Fractional (Expression params tables ('Required (nullity ty))) where
141+ (/) = unsafeBinaryOp "/"
142+ fromRational x = fromInteger (numerator x) / fromInteger (denominator x)
144+instance (PGFloating ty, PGCast 'PGNumeric ty, PGTyped ty)
145+ => Floating (Expression params tables ('Required (nullity ty))) where
146+ pi = UnsafeExpression "pi()"
147+ exp = unsafeFunction "exp"
148+ log = unsafeFunction "ln"
149+ sqrt = unsafeFunction "sqrt"
150+ b ** x = UnsafeExpression $
151+ "power(" <> renderExpression b <> ", " <> renderExpression x <> ")"
152+ logBase b y = cast pgtype $ logBaseNumeric b y
155+ :: Expression params tables ('Required (nullity ty))
156+ -> Expression params tables ('Required (nullity ty))
157+ -> Expression params tables ('Required (nullity 'PGNumeric))
158+ logBaseNumeric b' y' = UnsafeExpression $ mconcat
160+ , renderExpression b' <> "::numeric"
162+ , renderExpression y' <> "::numeric"
165+ sin = unsafeFunction "sin"
166+ cos = unsafeFunction "cos"
167+ tan = unsafeFunction "tan"
168+ asin = unsafeFunction "asin"
169+ acos = unsafeFunction "acos"
170+ atan = unsafeFunction "atan"
171+ sinh x = (exp x - exp (-x)) / 2
172+ cosh x = (exp x + exp (-x)) / 2
173+ tanh x = sinh x / cosh x
174+ asinh x = log (x + sqrt (x*x + 1))
175+ acosh x = log (x + sqrt (x*x - 1))
176+ atanh x = log ((1 + x) / (1 - x)) / 2
178+class PGCast (ty0 :: PGType) (ty1 :: PGType) where
180+ :: TypeExpression ('Required ('Null ty1))
181+ -> Expression params tables ('Required (nullity ty0))
182+ -> Expression params tables ('Required (nullity ty1))
183+ cast ty x = UnsafeExpression $
184+ "(" <> renderExpression x <> "::" <> renderTypeExpression ty <> ")"
185+instance PGCast 'PGInt2 'PGInt2
186+instance PGCast 'PGInt2 'PGInt4
187+instance PGCast 'PGInt2 'PGInt8
188+instance PGCast 'PGInt4 'PGInt2
189+instance PGCast 'PGInt4 'PGInt4
190+instance PGCast 'PGInt4 'PGInt8
191+instance PGCast 'PGInt8 'PGInt2
192+instance PGCast 'PGInt8 'PGInt4
193+instance PGCast 'PGInt8 'PGInt8
194+instance PGCast 'PGInt8 'PGFloat4
195+instance PGCast 'PGInt8 'PGFloat8
196+instance PGCast 'PGInt8 'PGNumeric
198+instance (PGNum ty, PGTyped ty, PGCast 'PGInt8 ty)
199+ => NumB (Expression params tables ('Required (nullity ty))) where
200+ type IntegerOf (Expression params tables ('Required (nullity ty)))
201+ = (Expression params tables ('Required (nullity 'PGInt8)))
202+ fromIntegerB = cast pgtype
204+instance (PGNum ty, PGTyped ty, PGCast 'PGInt8 ty, PGCast ty 'PGInt8)
205+ => IntegralB (Expression params tables ('Required ('NotNull ty))) where
206+ quot = unsafeBinaryOp "/"
207+ rem = unsafeBinaryOp "%"
208+ div = unsafeBinaryOp "/"
209+ mod = unsafeBinaryOp "%"
210+ toIntegerB = cast int8
213+ ( IntegerOf (Expression params tables ('Required ('NotNull ty)))
214+ ~ (Expression params tables ('Required ('NotNull 'PGInt8)))
220+ => RealFracB (Expression params tables ('Required ('NotNull ty))) where
221+ properFraction x = (truncate x, x - unsafeFunction "trunc" x)
222+ truncate = fromIntegerB . unsafeFunction "trunc"
223+ round = fromIntegerB . unsafeFunction "round"
224+ ceiling = fromIntegerB . unsafeFunction "ceiling"
225+ floor = fromIntegerB . unsafeFunction "floor"
228+ ( IntegerOf (Expression params tables ('Required ('NotNull ty)))
229+ ~ (Expression params tables ('Required ('NotNull 'PGInt8)))
233+ , PGCast 'PGNumeric ty
236+ => RealFloatB (Expression params tables ('Required ('NotNull ty))) where
237+ isNaN x = x ==* UnsafeExpression "\'NaN\'"
238+ isInfinite x = x ==* UnsafeExpression "\'Infinity\'"
239+ ||* x ==* UnsafeExpression "\'-Infinity\'"
240+ isNegativeZero x = x ==* UnsafeExpression "-0"
242+ atan2 y x = UnsafeExpression $
243+ "atan2(" <> renderExpression y <> ", " <> renderExpression x <> ")"
135instance IsString (Expression params tables ('Required (nullity 'PGText))) where
245instance IsString (Expression params tables ('Required (nullity 'PGText))) where
136 fromString str = UnsafeExpression $
246 fromString str = UnsafeExpression $
@@ -467,16 +577,93 @@ newtype TypeExpression (ty :: ColumnType)
467 = UnsafeTypeExpression { renderTypeExpression :: ByteString }
577 = UnsafeTypeExpression { renderTypeExpression :: ByteString }
468 deriving (Show,Eq)
578 deriving (Show,Eq)
580+bool :: TypeExpression ('Required ('Null 'PGBool))
581+bool = UnsafeTypeExpression "bool"
470int2 :: TypeExpression ('Required ('Null 'PGInt2))
582int2 :: TypeExpression ('Required ('Null 'PGInt2))
471int2 = UnsafeTypeExpression "int2"
583int2 = UnsafeTypeExpression "int2"
584+smallint :: TypeExpression ('Required ('Null 'PGInt2))
585+smallint = UnsafeTypeExpression "smallint"
472int4 :: TypeExpression ('Required ('Null 'PGInt4))
586int4 :: TypeExpression ('Required ('Null 'PGInt4))
473int4 = UnsafeTypeExpression "int4"
587int4 = UnsafeTypeExpression "int4"
588+int :: TypeExpression ('Required ('Null 'PGInt4))
589+int = UnsafeTypeExpression "int"
590+integer :: TypeExpression ('Required ('Null 'PGInt4))
591+integer = UnsafeTypeExpression "integer"
474int8 :: TypeExpression ('Required ('Null 'PGInt8))
592int8 :: TypeExpression ('Required ('Null 'PGInt8))
475int8 = UnsafeTypeExpression "int8"
593int8 = UnsafeTypeExpression "int8"
594+bigint :: TypeExpression ('Required ('Null 'PGInt8))
595+bigint = UnsafeTypeExpression "bigint"
596+numeric :: TypeExpression ('Required ('Null 'PGNumeric))
597+numeric = UnsafeTypeExpression "numeric"
476−bool :: TypeExpression ('Required ('Null 'PGBool))
598+float4 :: TypeExpression ('Required ('Null 'PGFloat4))
599+float4 = UnsafeTypeExpression "float4"
600+real :: TypeExpression ('Required ('Null 'PGFloat4))
601+real = UnsafeTypeExpression "real"
602+float8 :: TypeExpression ('Required ('Null 'PGFloat8))
603+float8 = UnsafeTypeExpression "float8"
604+doublePrecision :: TypeExpression ('Required ('Null 'PGFloat8))
605+doublePrecision = UnsafeTypeExpression "double precision"
606+serial2 :: TypeExpression ('Optional ('NotNull 'PGInt2))
607+serial2 = UnsafeTypeExpression "serial2"
608+smallserial :: TypeExpression ('Optional ('NotNull 'PGInt2))
609+smallserial = UnsafeTypeExpression "smallserial"
610+serial4 :: TypeExpression ('Optional ('NotNull 'PGInt4))
477−bool = UnsafeTypeExpression "bool"
611+serial4 = UnsafeTypeExpression "serial4"
612+serial :: TypeExpression ('Optional ('NotNull 'PGInt4))
613+serial = UnsafeTypeExpression "serial"
614+serial8 :: TypeExpression ('Optional ('NotNull 'PGInt8))
615+serial8 = UnsafeTypeExpression "serial8"
616+bigserial :: TypeExpression ('Optional ('NotNull 'PGInt8))
617+bigserial = UnsafeTypeExpression "bigserial"
618+money :: TypeExpression ('Optional ('NotNull 'PGMoney))
619+money = UnsafeTypeExpression "money"
478text :: TypeExpression ('Required ('Null 'PGText))
620text :: TypeExpression ('Required ('Null 'PGText))
479text = UnsafeTypeExpression "text"
621text = UnsafeTypeExpression "text"
625+ -> TypeExpression ('Optional ('NotNull ('PGChar n)))
626+char (_ :: proxy n) = UnsafeTypeExpression $
627+ "char(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
631+ -> TypeExpression ('Optional ('NotNull ('PGChar n)))
632+character (_ :: proxy n) = UnsafeTypeExpression $
633+ "character(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
637+ -> TypeExpression ('Optional ('NotNull ('PGVarChar n)))
638+varchar (_ :: proxy n) = UnsafeTypeExpression $
639+ "varchar(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
643+ -> TypeExpression ('Optional ('NotNull ('PGVarChar n)))
644+characterVarying (_ :: proxy n) = UnsafeTypeExpression $
645+ "character varying(" <> fromString (show (natVal' (proxy# :: Proxy# n))) <> ")"
646+bytea :: TypeExpression ('Optional ('NotNull ('PGBytea)))
647+bytea = UnsafeTypeExpression "bytea"
648+timestamp :: TypeExpression ('Optional ('NotNull ('PGTimestamp)))
649+timestamp = UnsafeTypeExpression "timestamp"
650+timestampWithTimeZone :: TypeExpression ('Optional ('NotNull ('PGTimestampTZ)))
651+timestampWithTimeZone = UnsafeTypeExpression "timestamp with time zone"
652+date :: TypeExpression ('Optional ('NotNull ('PGDate)))
653+date = UnsafeTypeExpression "date"
654+time :: TypeExpression ('Optional ('NotNull ('PGTime)))
655+time = UnsafeTypeExpression "time"
656+timeWithTimeZone :: TypeExpression ('Optional ('NotNull ('PGTimeTZ)))
657+timeWithTimeZone = UnsafeTypeExpression "time with time zone"
658+interval :: TypeExpression ('Optional ('NotNull ('PGInterval)))
659+interval = UnsafeTypeExpression "interval"
660+uuid :: TypeExpression ('Optional ('NotNull ('PGUuid)))
661+uuid = UnsafeTypeExpression "uuid"
662+json :: TypeExpression ('Optional ('NotNull ('PGJson)))
663+json = UnsafeTypeExpression "json"
664+jsonb :: TypeExpression ('Optional ('NotNull ('PGJsonb)))
665+jsonb = UnsafeTypeExpression "jsonb"
481 :: TypeExpression ('Required ('Null ty))
668 :: TypeExpression ('Required ('Null ty))
482 -> TypeExpression ('Required ('NotNull ty))
669 -> TypeExpression ('Required ('NotNull ty))
@@ -487,8 +674,14 @@ default_
487 -> TypeExpression ('Optional ty)
674 -> TypeExpression ('Optional ty)
488default_ x ty = UnsafeTypeExpression $
675default_ x ty = UnsafeTypeExpression $
489 renderTypeExpression ty <> " DEFAULT " <> renderExpression x
676 renderTypeExpression ty <> " DEFAULT " <> renderExpression x
490−serial :: TypeExpression ('Optional ('NotNull 'PGInt4))
677+
491−serial = UnsafeTypeExpression "serial"
678+class PGTyped (ty :: PGType) where
679+ pgtype :: TypeExpression ('Required ('Null ty))
680+instance PGTyped 'PGInt2 where pgtype = int2
681+instance PGTyped 'PGInt4 where pgtype = int4
682+instance PGTyped 'PGInt8 where pgtype = int8
683+instance PGTyped 'PGBool where pgtype = bool
684+instance PGTyped 'PGText where pgtype = text
493createTable
686createTable
494 :: (KnownSymbol table, SListI columns)
687 :: (KnownSymbol table, SListI columns)