@@ -1,8 +1,11 @@
1{-# LANGUAGE
1{-# LANGUAGE
3 , FlexibleInstances
4 , FlexibleInstances
5 , MultiParamTypeClasses
7 , MultiParamTypeClasses
6 , OverloadedStrings
9 , OverloadedStrings
7 , PolyKinds
10 , PolyKinds
8 , RankNTypes
11 , RankNTypes
@@ -20,82 +23,77 @@ import Data.Monoid
20import Data.Proxy
23import Data.Proxy
21import Data.String
24import Data.String
22import Data.Vinyl
25import Data.Vinyl
23−-- import Data.Vinyl.Functor
26+import GHC.OverloadedLabels
24import GHC.TypeLits
27import GHC.TypeLits
26−-- import qualified Data.ByteString as ByteString
27import qualified Data.ByteString.Char8 as Char8
29import qualified Data.ByteString.Char8 as Char8
29import Squeel.PostgreSQL.Type
31import Squeel.PostgreSQL.Type
31−newtype Expression ps xs y =
32− UnsafeExpression { renderExpression :: ByteString }
34−param1 :: Expression (p1:ps) cols p1
35−param1 = UnsafeExpression "$1"
36−param2 :: Expression (p1:p2:ps) cols p2
37−param2 = UnsafeExpression "$2"
38−param3 :: Expression (p1:p2:p3:ps) cols p3
39−param3 = UnsafeExpression "$3"
40−param4 :: Expression (p1:p2:p3:p4:ps) cols p4
41−param4 = UnsafeExpression "$4"
42−param5 :: Expression (p1:p2:p3:p4:p5:ps) cols p5
43−param5 = UnsafeExpression "$5"
45−class HasField ident xs x where
33+class HasField label xs x where
46− fieldName :: Proxy ident -> Proxy xs -> Proxy x -> ByteString
34+ fieldName :: Proxy label -> Proxy xs -> Proxy x -> ByteString
35+instance {-# OVERLAPPING #-} KnownSymbol label
47−instance KnownSymbol name => HasField '[name] ((name ':= x) ': xs) x where
36+ => HasField label ('(label, x) ': xs) x where
48− fieldName _ _ _ = Char8.pack (symbolVal (Proxy @name))
37+ fieldName _ _ _ = Char8.pack (symbolVal (Proxy @label))
38+instance {-# OVERLAPPABLE #-} HasField label xs y
49−instance HasField ident xs x => HasField ident (y ': xs) x where
39+ => HasField label (x ': xs) y where
50− fieldName _ _ _ = fieldName (Proxy @ident) (Proxy @xs) (Proxy @x)
40+ fieldName _ _ _ = fieldName (Proxy @label) (Proxy @xs) (Proxy @y)
51−instance (KnownSymbol name, HasField names xs x)
41+
52− => HasField (name ': names) ((name ':= xs) ': xss) x where
42+data Alias label = Alias
53− fieldName _ _ _ = Char8.pack (symbolVal (Proxy @name))
43+data Aliased obj labeled where
54− <> "." <> fieldName (Proxy @names) (Proxy @xs) (Proxy @x)
44+ As :: obj x -> Alias label -> Aliased obj '(label, x)
55−
45+instance IsLabel label (Alias label) where fromLabel _ = Alias
56−column_
46+instance IsLabel label (obj x)
57− :: forall ident xs x ps
47+ => IsLabel label (Aliased obj '(label, x)) where
58− . HasField ident xs x
48+ fromLabel p = fromLabel p `As` fromLabel p
60− -> Expression ps xs x
50+alias :: Aliased obj '(label, x) -> Alias label
61−column_ (_ :: Proxy ident) = UnsafeExpression $
51+alias _ = Alias
62− fieldName (Proxy @ident) (Proxy @xs) (Proxy @x)
52+
64−data Identified ident x = (:=) ident x
65−data Aliased obj named where AS :: obj x -> Aliased obj (name ':= x)
67−unalias :: Aliased obj (name ':= x) -> obj x
53+unalias :: Aliased obj '(label, x) -> obj x
68−unalias (AS obj) = obj
54+unalias (obj `As` _) = obj
71− :: forall ident xs x ps
72− . HasField ident xs x
73− => Aliased (Expression ps xs) (ident ':= x)
74−column = AS $ column_ (Proxy @ident)
76renderAliased
56renderAliased
77− :: KnownSymbol name
57+ :: KnownSymbol label
78 => (obj x -> ByteString)
58 => (obj x -> ByteString)
79− -> Aliased obj (name ':= x)
59+ -> Aliased obj '(label, x)
80 -> ByteString
60 -> ByteString
81−renderAliased render (AS obj :: Aliased obj (name ':= x)) =
61+renderAliased render (obj `As` label) =
82− render obj <> " AS " <> Char8.pack (symbolVal (Proxy @name))
62+ render obj <> " AS " <> Char8.pack (symbolVal label)
84class AllAliased xs where
64class AllAliased xs where
85 renderAllAliased
65 renderAllAliased
86 :: (forall x. obj x -> ByteString)
66 :: (forall x. obj x -> ByteString)
87 -> Rec (Aliased obj) xs
67 -> Rec (Aliased obj) xs
88 -> ByteString
68 -> ByteString
89−instance KnownSymbol name => AllAliased '[name ':= x] where
69+instance KnownSymbol label => AllAliased '[ '(label, x)] where
90 renderAllAliased render
70 renderAllAliased render
91− (aliased :& RNil :: Rec (Aliased obj) '[name ':= x]) =
71+ (aliased :& RNil :: Rec (Aliased obj) '[ '(label, x)]) =
92 renderAliased render aliased
72 renderAliased render aliased
93−instance (KnownSymbol name, AllAliased xs)
73+instance (KnownSymbol label, AllAliased (x' ': xs))
94− => AllAliased ((name ':= x) ': xs) where
74+ => AllAliased ('(label, x) ': (x' ': xs)) where
95 renderAllAliased render
75 renderAllAliased render
96− (x :& xs :: Rec (Aliased obj) ((name ':= x) ': xs)) =
76+ (x :& xs :: Rec (Aliased obj) ('(label, x) ': x' : xs)) =
97 renderAliased render x <> ", " <> renderAllAliased render xs
77 renderAliased render x <> ", " <> renderAllAliased render xs
79+newtype Expression ps xs y =
80+ UnsafeExpression { renderExpression :: ByteString }
82+param1 :: Expression (p1:ps) cols p1
83+param1 = UnsafeExpression "$1"
84+param2 :: Expression (p1:p2:ps) cols p2
85+param2 = UnsafeExpression "$2"
86+param3 :: Expression (p1:p2:p3:ps) cols p3
87+param3 = UnsafeExpression "$3"
88+param4 :: Expression (p1:p2:p3:p4:ps) cols p4
89+param4 = UnsafeExpression "$4"
90+param5 :: Expression (p1:p2:p3:p4:p5:ps) cols p5
91+param5 = UnsafeExpression "$5"
93+instance HasField label xs x => IsLabel label (Expression ps xs x) where
94+ fromLabel _ = UnsafeExpression $
95+ fieldName (Proxy @label) (Proxy @xs) (Proxy @x)
99instance IsString (Expression ps xs 'PGText) where
97instance IsString (Expression ps xs 'PGText) where
100 fromString str = UnsafeExpression $ "\'" <> fromString str <> "\'"
98 fromString str = UnsafeExpression $ "\'" <> fromString str <> "\'"
@@ -149,47 +147,52 @@ project
149 -> Projection ps xs ys
147 -> Projection ps xs ys
150project = UnsafeProjection . renderAllAliased renderExpression
148project = UnsafeProjection . renderAllAliased renderExpression
152−newtype Relation ps xss ys = UnsafeRelation
150+data Tabulation ps xss xs = UnsafeTabulation
153− { renderRelation :: ByteString }
151+ { renderTabulation :: ByteString }
155−table_
153+data Relation ps xss xs = Relation
156− :: forall ident xss xs ps
154+ { tabulation :: Tabulation ps xss xs
157− . HasField ident xss xs
159− -> Relation ps xss xs
160−table_ (_ :: Proxy ident) = UnsafeRelation $
161− fieldName (Proxy @ident) (Proxy @xss) (Proxy @xs)
164− :: forall ident xss xs ps
165− . HasField ident xss xs
166− => Aliased (Relation ps xss) (ident ':= xs)
167−table = AS $ table_ (Proxy @ident)
169−data Selection ps xss xs ys = Selection
170− { projection :: Projection ps xs ys
171− , relation :: Relation ps xss xs
172 , restriction :: Maybe (Expression ps xs 'PGBool)
155 , restriction :: Maybe (Expression ps xs 'PGBool)
175−renderSelection :: Selection ps xss xs ys -> ByteString
158+renderRelation :: Relation ps xss xs -> ByteString
176−renderSelection (Selection xs ys wh) =
159+renderRelation (Relation tab wh) =
177− renderProjection xs <> " FROM " <> renderRelation ys
178− <> maybe "" ((" WHERE " <>) . renderExpression) wh
160+ renderTabulation tab <> maybe "" ((" WHERE " <>) . renderExpression) wh
180−from :: Projection ps xs ys -> Relation ps xss xs -> Selection ps xss xs ys
181−ys `from` xs = Selection ys xs Nothing
184− :: Selection ps xss xs ys
163+ :: Relation ps xss xs
185 -> Expression ps xs 'PGBool
164 -> Expression ps xs 'PGBool
186− -> Selection ps xss xs ys
165+ -> Relation ps xss xs
187ys `where_` condition = ys
166ys `where_` condition = ys
188 { restriction = case restriction ys of
167 { restriction = case restriction ys of
189 Nothing -> Just condition
168 Nothing -> Just condition
190− Just conditions -> Just (condition &&* conditions)
169+ Just conditions -> Just (conditions &&* condition)
172+instance HasField label xss xs
173+ => IsLabel label (Relation ps xss xs) where
174+ fromLabel _ = Relation
175+ { tabulation = UnsafeTabulation $
176+ fieldName (Proxy @label) (Proxy @xss) (Proxy @xs)
177+ , restriction = Nothing
180+newtype Selection ps xss ys = UnsafeSelection
181+ { renderSelection :: ByteString }
183+from :: Projection ps xs ys -> Relation ps xss xs -> Selection ps xss ys
184+ys `from` xs = UnsafeSelection $
185+ renderProjection ys <> " FROM " <> renderRelation xs
187+subselect :: Selection ps xss ys -> Relation ps xss ys
188+subselect selection = Relation
189+ { tabulation = UnsafeTabulation $ "SELECT " <> renderSelection selection
190+ , restriction = Nothing
193newtype Query ps xss yss zs = UnsafeQuery { renderQuery :: ByteString }
193newtype Query ps xss yss zs = UnsafeQuery { renderQuery :: ByteString }
194newtype PreparedQuery ps xss yss zs =
194newtype PreparedQuery ps xss yss zs =
195 UnsafePreparedQuery { renderPreparedQuery :: ByteString }
195 UnsafePreparedQuery { renderPreparedQuery :: ByteString }
197+select :: Selection ps xss ys -> Query ps xss xss ys
198+select selection = UnsafeQuery $ "SELECT " <> renderSelection selection <> ";"