on dev help sign in
inserts
6253103Eitan Chatav
squeel-postgresql/src/Squeel/PostgreSQL/Query.hs+31−6
@@ -47,6 +47,9 @@ instance IsLabel label (obj x)
47 => IsLabel label (Aliased obj '(label, x)) where
47 => IsLabel label (Aliased obj '(label, x)) where
48 fromLabel p = fromLabel p `As` fromLabel p
48 fromLabel p = fromLabel p `As` fromLabel p
49
49
50+aliasName :: forall label. KnownSymbol label => Alias label -> ByteString
51+aliasName _ = Char8.pack (symbolVal (Proxy @label))
52+
50alias :: Aliased obj '(label, x) -> Alias label
53alias :: Aliased obj '(label, x) -> Alias label
51alias _ = Alias
54alias _ = Alias
52
55
@@ -61,6 +64,23 @@ renderAliased
61renderAliased render (obj `As` label) =
64renderAliased render (obj `As` label) =
62 render obj <> " AS " <> Char8.pack (symbolVal label)
65 render obj <> " AS " <> Char8.pack (symbolVal label)
63
66
67+class UnzipAliased (xs :: [(Symbol,k)]) where
68+ type Unaliased xs :: [k]
69+ unzipAliased
70+ :: Rec (Aliased obj) xs
71+ -> ([ByteString], Rec obj (Unaliased xs))
72+instance UnzipAliased '[] where
73+ type Unaliased '[] = '[]
74+ unzipAliased _ = ([], RNil)
75+instance (KnownSymbol label, UnzipAliased xs)
76+ => UnzipAliased ( '(label, x) ': xs) where
77+ type Unaliased ( '(label, x) ': xs) = x ': Unaliased xs
78+ unzipAliased (x :& xs) =
79+ let
80+ (labels,values) = unzipAliased xs
81+ in
82+ (aliasName (alias x) : labels, unalias x :& values)
83+
64class AllAliased xs where
84class AllAliased xs where
65 renderAllAliased
85 renderAllAliased
66 :: (forall x. obj x -> ByteString)
86 :: (forall x. obj x -> ByteString)
@@ -234,19 +254,24 @@ subselect selection = Relation
234 , offsetting = Nothing
254 , offsetting = Nothing
235 }
255 }
236
256
237−newtype Insertion ps xss = UnsafeInsertion {renderInsertion :: ByteString }
257+newtype Insertion ps xss xs = UnsafeInsertion
258+ {renderInsertion :: ByteString }
238
259
239into
260into
240 :: forall label xss xs ps
261 :: forall label xss xs ps
241− . HasField label xss xs
262+ . (HasField label xss xs, UnzipAliased xs)
242 => Proxy label
263 => Proxy label
243 -> Rec (Aliased (Expression ps '[])) xs
264 -> Rec (Aliased (Expression ps '[])) xs
244− -> Insertion ps xss
265+ -> Insertion ps xss xs
245into table values = UnsafeInsertion $ "INTO "
266into table values = UnsafeInsertion $ "INTO "
246 <> fieldName table (Proxy @xss) (Proxy @xs)
267 <> fieldName table (Proxy @xss) (Proxy @xs)
268+ <> " (" <> ByteString.intercalate ", " names
247− <> " VALUES "
269+ <> ") VALUES ("
248 <> ByteString.intercalate ", "
270 <> ByteString.intercalate ", "
249− (recordToList (rmap (Const . renderExpression . unalias) values))
271+ (recordToList (rmap (Const . renderExpression) exprs))
272+ <> ")"
273+ where
274+ (names,exprs) = unzipAliased values
250
275
251newtype Query ps xss yss zs = UnsafeQuery { renderQuery :: ByteString }
276newtype Query ps xss yss zs = UnsafeQuery { renderQuery :: ByteString }
252newtype PreparedQuery ps xss yss zs =
277newtype PreparedQuery ps xss yss zs =
@@ -256,6 +281,6 @@ select :: Selection ps xss ys -> Query ps xss xss ys
256select selection = UnsafeQuery $
281select selection = UnsafeQuery $
257 "SELECT " <> renderSelection selection <> ";"
282 "SELECT " <> renderSelection selection <> ";"
258
283
259−insert :: Insertion ps xss -> Query ps xss xss '[]
284+insert :: Insertion ps xss xs -> Query ps xss xss '[]
260insert insertion = UnsafeQuery $
285insert insertion = UnsafeQuery $
261 "INSERT " <> renderInsertion insertion <> ";"
286 "INSERT " <> renderInsertion insertion <> ";"
squeel-postgresql/test/Squeel/PostgreSQL/QuerySpec.hs+5−16
@@ -52,20 +52,12 @@ spec = do
52 it "correctly render simple INSERTs" $ do
52 it "correctly render simple INSERTs" $ do
53 renderQuery (insert insertion)
53 renderQuery (insert insertion)
54 `shouldBe`
54 `shouldBe`
55− "INSERT INTO "
55+ "INSERT INTO table1 (col1, col2) VALUES (2, 4);"
56−
57−
58−type Columns =
59− '[ '("col1", 'PGInt4)
60− , '("col2", 'PGInt4)
61− ]
62
56
57+type Columns = '[ '("col1", 'PGInt4), '("col2", 'PGInt4)]
63type Tables = '[ '("table1", Columns)]
58type Tables = '[ '("table1", Columns)]
64
59
65−sumAndCol1 :: Projection '[] Columns
60+sumAndCol1 :: Projection '[] Columns '[ '("sum", 'PGInt4), '("col1", 'PGInt4)]
66− '[ '("sum", 'PGInt4)
67− , '("col1", 'PGInt4)
68− ]
69sumAndCol1 = project ((#col1 + #col2) `As` #sum :& #col1 :& RNil)
61sumAndCol1 = project ((#col1 + #col2) `As` #sum :& #col1 :& RNil)
70
62
71table1 :: Relation '[] Tables Columns
63table1 :: Relation '[] Tables Columns
@@ -74,8 +66,5 @@ table1 = #table1
74parameterizedTable1 :: Relation '[ 'PGInt8] Tables Columns
66parameterizedTable1 :: Relation '[ 'PGInt8] Tables Columns
75parameterizedTable1 = #table1
67parameterizedTable1 = #table1
76
68
77−insertion :: Insertion '[] Tables
69+insertion :: Insertion '[] Tables Columns
78−insertion = into (Proxy @"table1") values
70+insertion = into (Proxy @"table1") (2 `As` #col1 :& 4 `As` #col2 :& RNil)
79−
80−values :: Rec (Expression '[] '[]) '[ 'PGInt4, 'PGInt4]
81−values = (2 `AS` #col1 :& 4 `AS` #col2 :& RNil)