@@ -1 +1,116 @@
1+{-# LANGUAGE
2+ DataKinds
3+ , FlexibleInstances
4+ , GADTs
5+ , LambdaCase
6+ , OverloadedStrings
7+ , PolyKinds
8+ , RankNTypes
9+ , ScopedTypeVariables
10+ , TypeApplications
11+ , TypeOperators
12+#-}
13+
114module Squeel.PostgreSQL.Query.Expression where
15+
16+import Data.ByteString (ByteString)
17+import Data.Monoid
18+import Data.Proxy
19+import Data.String
20+
21+import qualified PostgreSQL.Binary.Encoder as Encoder
22+
23+import Squeel.PostgreSQL.Value
24+import Squeel.PostgreSQL.Type
25+
26+data Expression (ps :: [PGType]) (cols :: [Column]) (x :: PGType) =
27+ Expression { unExpression :: ByteString } deriving Show
28+
29+param1 :: Expression (p1:ps) cols p1
30+param1 = Expression "$1"
31+
32+param2 :: Expression (p1:p2:ps) cols p2
33+param2 = Expression "$2"
34+
35+param3 :: Expression (p1:p2:p3:ps) cols p3
36+param3 = Expression "$3"
37+
38+param4 :: Expression (p1:p2:p3:p4:ps) cols p4
39+param4 = Expression "$4"
40+
41+param5 :: Expression (p1:p2:p3:p4:p5:ps) cols p5
42+param5 = Expression "$5"
43+
44+whenThen :: (Expression ps cols x,Expression ps cols y) -> ByteString
45+whenThen (Expression when_,Expression then_) = mconcat
46+ [" WHEN ",when_," THEN ",then_,"\n"]
47+
48+case_
49+ :: [(Expression ps cols ('PGType "bool"),Expression ps cols x)]
50+ -> Expression ps cols x
51+ -> Expression ps cols x
52+case_ whens (Expression else_) = Expression $ mconcat
53+ [ "CASE\n"
54+ , mconcat (map whenThen whens)
55+ , " ELSE ",else_
56+ , "\nEND"
57+ ]
58+
59+caseSwitch
60+ :: Expression ps cols x
61+ -> [(Expression ps cols x,Expression ps cols y)]
62+ -> Expression ps cols y
63+ -> Expression ps cols y
64+caseSwitch (Expression val) whens (Expression else_) = Expression $ mconcat
65+ [ "CASE ",val,"\n"
66+ , mconcat (map whenThen whens)
67+ , " ELSE ",else_
68+ ,"\nEND"
69+ ]
70+
71+(.==)
72+ :: Expression ps cols x
73+ -> Expression ps cols x
74+ -> Expression ps cols ('PGType "bool")
75+(.==) (Expression x1) (Expression x2) = Expression $ x1 <> "=" <> x2
76+
77+(./=)
78+ :: Expression ps cols x
79+ -> Expression ps cols x
80+ -> Expression ps cols ('PGType "bool")
81+(./=) (Expression x1) (Expression x2) = Expression $ x1 <> "<>" <> x2
82+
83+(.>)
84+ :: Expression ps cols x
85+ -> Expression ps cols x
86+ -> Expression ps cols ('PGType "bool")
87+(.>) (Expression x1) (Expression x2) = Expression $ x1 <> ">" <> x2
88+
89+(.<)
90+ :: Expression ps cols x
91+ -> Expression ps cols x
92+ -> Expression ps cols ('PGType "bool")
93+(.<) (Expression x1) (Expression x2) = Expression $ x1 <> "<" <> x2
94+
95+(.>=)
96+ :: Expression ps cols x
97+ -> Expression ps cols x
98+ -> Expression ps cols ('PGType "bool")
99+(.>=) (Expression x1) (Expression x2) = Expression $ x1 <> ">=" <> x2
100+
101+(.<=)
102+ :: Expression ps cols x
103+ -> Expression ps cols x
104+ -> Expression ps cols ('PGType "bool")
105+(.<=) (Expression x1) (Expression x2) = Expression $ x1 <> "<=" <> x2
106+
107+instance IsString (Expression ps cols ('PGType "text")) where
108+ fromString str = Expression $ "\'" <> fromString str <> "\'"
109+
110+instance Num (Expression ps cols ('PGType "int4")) where
111+ fromInteger n = Expression . fromString $ show n
112+ Expression x + Expression y = Expression $ x <> "+" <> y
113+ Expression x * Expression y = Expression $ x <> "*" <> y
114+ Expression x - Expression y = Expression $ x <> "+" <> y
115+ abs (Expression x) = Expression $ "@" <> x
116+ signum (Expression x) = Expression $ "sign(" <> x <> ")"