on dev help sign in
NULLs
commit7485e50fceebf8bedce9a723b2f11b5afcba25a2 authorEitan Chatav <eitan.chatav@gmail.com> dateSat 10 Jun 2017, 17:44 (9 years ago) parentb865f94
3 files changed+117−40
squeel-postgresql/src/Squeel/PostgreSQL/PQ.hs+2−2 squeel-postgresql/src/Squeel/PostgreSQL/Schema.hs+44−4 squeel-postgresql/src/Squeel/PostgreSQL/Statement.hs+71−34
squeel-postgresql/src/Squeel/PostgreSQL/PQ.hs+2−2
@@ -35,8 +35,8 @@ import Squeel.PostgreSQL.Schema
3535newtype Connection db = Connection { unConnection :: LibPQ.Connection }
3636
3737newtype PQ
38− (db0 :: [(Symbol,[(Symbol,PGType)])])
39− (db1 :: [(Symbol,[(Symbol,PGType)])])
38+ (db0 :: [(Symbol,[(Symbol,NullityType)])])
39+ (db1 :: [(Symbol,[(Symbol,NullityType)])])
4040 (m :: * -> *)
4141 (x :: *) =
4242 PQ { runPQ :: Connection db0 -> m (x, Connection db1) }
squeel-postgresql/src/Squeel/PostgreSQL/Schema.hs+44−4
@@ -9,6 +9,7 @@
99 , PolyKinds
1010 , RankNTypes
1111 , ScopedTypeVariables
12+ , TypeFamilies
1213 , TypeOperators
1314#-}
1415
@@ -23,6 +24,10 @@ module Squeel.PostgreSQL.Schema
2324 , KnownPGType (..)
2425 , KnownColumns (..)
2526 , renderAliased
27+ , NullityType (..)
28+ , NullifyType
29+ , NullifyColumns
30+ , NullifyTable
2631 , module GHC.OverloadedLabels
2732 , module GHC.TypeLits
2833 ) where
@@ -134,24 +139,59 @@ instance KnownPGType 'PGUuid where renderPGType _ = "uuid"
134139instance KnownPGType 'PGJson where renderPGType _ = "json"
135140instance KnownPGType 'PGJsonb where renderPGType _ = "jsonb"
136141
137−class KnownColumns (columns :: [(Symbol,PGType)]) where
142+class KnownColumns (columns :: [(Symbol,NullityType)]) where
138143 renderColumns :: Proxy# columns -> ByteString
139144instance
140145 ( KnownSymbol column
141146 , KnownPGType ty
142− ) => KnownColumns '[column ::: ty] where
147+ ) => KnownColumns '[column ::: 'NotNull ty] where
143148 renderColumns _ =
144149 fromString (symbolVal' (proxy# :: Proxy# column))
145150 <> " "
146151 <> renderPGType (proxy# :: Proxy# ty)
152+ <> " NOT NULL"
153+instance
154+ ( KnownSymbol column
155+ , KnownPGType ty
156+ ) => KnownColumns '[column ::: 'Null ty] where
157+ renderColumns _ =
158+ fromString (symbolVal' (proxy# :: Proxy# column))
159+ <> " "
160+ <> renderPGType (proxy# :: Proxy# ty)
161+ <> " NULL"
162+instance
163+ ( KnownSymbol column
164+ , KnownPGType ty
165+ , KnownColumns (columnsHead ': columnsTail)
166+ ) => KnownColumns ((column ::: 'NotNull ty) ': columnsHead ': columnsTail) where
167+ renderColumns _ =
168+ fromString (symbolVal' (proxy# :: Proxy# column))
169+ <> " "
170+ <> renderPGType (proxy# :: Proxy# ty)
171+ <> " NOT NULL, "
172+ <> renderColumns (proxy# :: Proxy# (columnsHead ': columnsTail))
147173instance
148174 ( KnownSymbol column
149175 , KnownPGType ty
150176 , KnownColumns (columnsHead ': columnsTail)
151− ) => KnownColumns ((column ::: ty) ': columnsHead ': columnsTail) where
177+ ) => KnownColumns ((column ::: 'Null ty) ': columnsHead ': columnsTail) where
152178 renderColumns _ =
153179 fromString (symbolVal' (proxy# :: Proxy# column))
154180 <> " "
155181 <> renderPGType (proxy# :: Proxy# ty)
156− <> ", "
182+ <> " NULL, "
157183 <> renderColumns (proxy# :: Proxy# (columnsHead ': columnsTail))
184+
185+data NullityType = Null PGType | NotNull PGType
186+
187+type family NullifyType nullty where
188+ NullifyType ('Null ty) = 'Null ty
189+ NullifyType ('NotNull ty) = 'Null ty
190+
191+type family NullifyColumns columns where
192+ NullifyColumns '[] = '[]
193+ NullifyColumns ((column ::: ty) ': columns) =
194+ (column ::: (NullifyType ty)) ': (NullifyColumns columns)
195+
196+type family NullifyTable table where
197+ NullifyTable (table ::: columns) = table ::: NullifyColumns columns
squeel-postgresql/src/Squeel/PostgreSQL/Statement.hs+71−34
@@ -28,9 +28,9 @@ import qualified Data.ByteString as ByteString
2828import Squeel.PostgreSQL.Schema
2929
3030newtype Expression
31− (params :: [PGType])
32− (tables :: [(Symbol,[(Symbol,PGType)])])
33− (ty :: PGType)
31+ (params :: [NullityType])
32+ (tables :: [(Symbol,[(Symbol,NullityType)])])
33+ (ty :: NullityType)
3434 = UnsafeExpression { renderExpression :: ByteString }
3535
3636class KnownNat n => HasParameter (n :: Nat) params ty | n params -> ty where
@@ -94,7 +94,7 @@ unsafeFunction
9494unsafeFunction fn x = UnsafeExpression $ mconcat
9595 [fn, "(", renderExpression x, ")"]
9696
97−instance PGNum ty => Num (Expression params tables ty) where
97+instance PGNum ty => Num (Expression params tables (nullity ty)) where
9898 (+) = unsafeBinaryOp "+"
9999 (-) = unsafeBinaryOp "-"
100100 (*) = unsafeBinaryOp "*"
@@ -102,7 +102,7 @@ instance PGNum ty => Num (Expression params tables ty) where
102102 signum = unsafeFunction "sign"
103103 fromInteger = UnsafeExpression . fromString . show
104104
105−instance IsString (Expression params tables 'PGText) where
105+instance IsString (Expression params tables (nullity 'PGText)) where
106106 fromString str = UnsafeExpression $
107107 "E\'" <> fromString (escape =<< str) <> "\'"
108108 where
@@ -117,7 +117,7 @@ instance IsString (Expression params tables 'PGText) where
117117 '\\' -> "\\\\"
118118 c -> [c]
119119
120−instance Boolean (Expression params tables 'PGBool) where
120+instance Boolean (Expression params tables ('NotNull 'PGBool)) where
121121 true = UnsafeExpression "TRUE"
122122 false = UnsafeExpression "FALSE"
123123 notB = unsafeUnaryOp "NOT"
@@ -125,10 +125,10 @@ instance Boolean (Expression params tables 'PGBool) where
125125 (||*) = unsafeBinaryOp "OR"
126126
127127type instance BooleanOf (Expression params tables ty) =
128− Expression params tables 'PGBool
128+ Expression params tables ('NotNull 'PGBool)
129129
130130caseWhenThenElse
131− :: [(Expression params tables 'PGBool, Expression params tables ty)]
131+ :: [(Expression params tables ('NotNull 'PGBool), Expression params tables ty)]
132132 -> Expression params tables ty
133133 -> Expression params tables ty
134134caseWhenThenElse whenThens else_ = UnsafeExpression $ mconcat
@@ -158,9 +158,9 @@ instance OrdB (Expression params tables ty) where
158158 (<=*) = unsafeBinaryOp "<="
159159
160160newtype TableRef
161− (params :: [PGType])
162− (schema :: [(Symbol,[(Symbol,PGType)])])
163− (tables :: [(Symbol,[(Symbol,PGType)])])
161+ (params :: [NullityType])
162+ (schema :: [(Symbol,[(Symbol,NullityType)])])
163+ (tables :: [(Symbol,[(Symbol,NullityType)])])
164164 = UnsafeTableRef { renderTableRef :: ByteString }
165165
166166class KnownSymbol table => HasTable table tables columns
@@ -182,7 +182,7 @@ crossJoin tab tabs = UnsafeTableRef $
182182
183183innerJoin
184184 :: TableRef params schema '[table]
185− -> Expression params (table ': tables) 'PGBool
185+ -> Expression params (table ': tables) ('NotNull 'PGBool)
186186 -> TableRef params schema tables
187187 -> TableRef params schema (table ': tables)
188188innerJoin tab on tabs = UnsafeTableRef $
@@ -192,10 +192,47 @@ innerJoin tab on tabs = UnsafeTableRef $
192192 <> " ON " <>
193193 renderExpression on
194194
195+leftOuterJoin
196+ :: TableRef params schema '[right]
197+ -> Expression params (right ': tables) ('NotNull 'PGBool)
198+ -> TableRef params schema (left : tables)
199+ -> TableRef params schema (NullifyTable right ': left ': tables)
200+leftOuterJoin tab on tabs = UnsafeTableRef $
201+ renderTableRef tabs
202+ <> " LEFT OUTER JOIN " <>
203+ renderTableRef tab
204+ <> " ON " <>
205+ renderExpression on
206+
207+rightOuterJoin
208+ :: TableRef params schema '[right]
209+ -> Expression params (right ': tables) ('NotNull 'PGBool)
210+ -> TableRef params schema (left : tables)
211+ -> TableRef params schema (right ': NullifyTable left ': tables)
212+rightOuterJoin tab on tabs = UnsafeTableRef $
213+ renderTableRef tabs
214+ <> " RIGHT OUTER JOIN " <>
215+ renderTableRef tab
216+ <> " ON " <>
217+ renderExpression on
218+
219+fullOuterJoin
220+ :: TableRef params schema '[right]
221+ -> Expression params (right ': tables) ('NotNull 'PGBool)
222+ -> TableRef params schema (left : tables)
223+ -> TableRef params schema
224+ (NullifyTable right ': NullifyTable left ': tables)
225+fullOuterJoin tab on tabs = UnsafeTableRef $
226+ renderTableRef tabs
227+ <> " FULL OUTER JOIN " <>
228+ renderTableRef tab
229+ <> " ON " <>
230+ renderExpression on
231+
195232data Clauses params tables = Clauses
196− { whereClause :: Maybe (Expression params tables 'PGBool)
197− , limitClause :: Maybe (Expression params '[] 'PGInt8)
198− , offsetClause :: Maybe (Expression params '[] 'PGInt8)
233+ { whereClause :: Maybe (Expression params tables ('NotNull 'PGBool))
234+ , limitClause :: Maybe (Expression params '[] ('NotNull 'PGInt8))
235+ , offsetClause :: Maybe (Expression params '[] ('NotNull 'PGInt8))
199236 }
200237
201238instance Monoid (Clauses params tables) where
@@ -219,9 +256,9 @@ instance Monoid (Clauses params tables) where
219256 }
220257
221258data TableExpression
222− (params :: [PGType])
223− (schema :: [(Symbol,[(Symbol,PGType)])])
224− (tables :: [(Symbol,[(Symbol,PGType)])])
259+ (params :: [NullityType])
260+ (schema :: [(Symbol,[(Symbol,NullityType)])])
261+ (tables :: [(Symbol,[(Symbol,NullityType)])])
225262 = TableExpression
226263 { tableRef :: TableRef params schema tables
227264 , clauses :: Clauses params tables
@@ -249,30 +286,30 @@ instance (HasTable table schema columns, table ~ table')
249286 fromLabel p = TableExpression (getTable p) mempty
250287
251288where_
252− :: Expression params tables 'PGBool
289+ :: Expression params tables ('NotNull 'PGBool)
253290 -> TableExpression params schema tables
254291 -> TableExpression params schema tables
255292where_ wh (TableExpression tabs clauses1) = TableExpression tabs
256293 (clauses1 <> Clauses (Just wh) Nothing Nothing)
257294
258295limit
259− :: Expression params '[] 'PGInt8
296+ :: Expression params '[] ('NotNull 'PGInt8)
260297 -> TableExpression params schema tables
261298 -> TableExpression params schema tables
262299limit lim (TableExpression tabs clauses1) = TableExpression tabs
263300 (clauses1 <> Clauses Nothing (Just lim) Nothing)
264301
265302offset
266− :: Expression params '[] 'PGInt8
303+ :: Expression params '[] ('NotNull 'PGInt8)
267304 -> TableExpression params schema tables
268305 -> TableExpression params schema tables
269306offset off (TableExpression tabs clauses1) = TableExpression tabs
270307 (clauses1 <> Clauses Nothing Nothing (Just off))
271308
272309newtype Selection
273− (params :: [PGType])
274− (schema :: [(Symbol,[(Symbol,PGType)])])
275− (columns :: [(Symbol,PGType)])
310+ (params :: [NullityType])
311+ (schema :: [(Symbol,[(Symbol,NullityType)])])
312+ (columns :: [(Symbol,NullityType)])
276313 = UnsafeSelection
277314 { renderSelection :: ByteString }
278315
@@ -282,12 +319,12 @@ starFrom
282319 -> Selection params schema columns
283320starFrom tabs = UnsafeSelection $ "* FROM " <> renderTabulation tabs
284321
285−tableStarFrom
322+dotStarFrom
286323 :: HasTable table tables columns
287324 => Alias table
288325 -> TableExpression params schema tables
289326 -> Selection params schema columns
290−Alias tab `tableStarFrom` tabs = UnsafeSelection $
327+Alias tab `dotStarFrom` tabs = UnsafeSelection $
291328 fromString (symbolVal' tab) <> ".* FROM" <> renderTabulation tabs
292329
293330from
@@ -303,17 +340,17 @@ list `from` tabs = UnsafeSelection $
303340 . rmap (Const . renderAliased renderExpression)
304341
305342newtype Statement
306− (params :: [PGType])
307− (schema0 :: [(Symbol,[(Symbol,PGType)])])
308− (schema1 :: [(Symbol,[(Symbol,PGType)])])
309− (columns :: [(Symbol,PGType)])
343+ (params :: [NullityType])
344+ (schema0 :: [(Symbol,[(Symbol,NullityType)])])
345+ (schema1 :: [(Symbol,[(Symbol,NullityType)])])
346+ (columns :: [(Symbol,NullityType)])
310347 = UnsafeStatement { renderStatement :: ByteString }
311348
312349newtype PreparedStatement
313− (params :: [PGType])
314− (schema0 :: [(Symbol,[(Symbol,PGType)])])
315− (schema1 :: [(Symbol,[(Symbol,PGType)])])
316− (columns :: [(Symbol,PGType)])
350+ (params :: [NullityType])
351+ (schema0 :: [(Symbol,[(Symbol,NullityType)])])
352+ (schema1 :: [(Symbol,[(Symbol,NullityType)])])
353+ (columns :: [(Symbol,NullityType)])
317354 = UnsafePreparedStatement { renderPreparedStatement :: ByteString }
318355
319356select