@@ -21,9 +21,11 @@ import Data.Monoid
2121import Data.Proxy
2222import Data.String
2323import Data.Vinyl
24+import Data.Vinyl.Functor
2425import GHC.OverloadedLabels
2526import GHC.TypeLits
2627
28+import qualified Data.ByteString as ByteString
2729import qualified Data.ByteString.Char8 as Char8
2830
2931import Squeel.PostgreSQL.Type
@@ -33,7 +35,7 @@ class HasField label xs x where
3335instance {-# OVERLAPPING #-} KnownSymbol label
3436 => HasField label ('(label, x) ': xs) x where
3537 fieldName _ _ _ = Char8.pack (symbolVal (Proxy @label))
36−instance HasField label xs y
38+instance {-# OVERLAPPABLE #-} HasField label xs y
3739 => HasField label (x ': xs) y where
3840 fieldName _ _ _ = fieldName (Proxy @label) (Proxy @xs) (Proxy @y)
3941
@@ -232,9 +234,28 @@ subselect selection = Relation
232234 , offsetting = Nothing
233235 }
234236
237+newtype Insertion ps xss = UnsafeInsertion {renderInsertion :: ByteString }
238+
239+into
240+ :: forall label xss xs ps
241+ . HasField label xss xs
242+ => Proxy label
243+ -> Rec (Aliased (Expression ps '[])) xs
244+ -> Insertion ps xss
245+into table values = UnsafeInsertion $ "INTO "
246+ <> fieldName table (Proxy @xss) (Proxy @xs)
247+ <> " VALUES "
248+ <> ByteString.intercalate ", "
249+ (recordToList (rmap (Const . renderExpression . unalias) values))
250+
235251newtype Query ps xss yss zs = UnsafeQuery { renderQuery :: ByteString }
236252newtype PreparedQuery ps xss yss zs =
237253 UnsafePreparedQuery { renderPreparedQuery :: ByteString }
238254
239255select :: Selection ps xss ys -> Query ps xss xss ys
240−select selection = UnsafeQuery $ "SELECT " <> renderSelection selection <> ";"
256+select selection = UnsafeQuery $
257+ "SELECT " <> renderSelection selection <> ";"
258+
259+insert :: Insertion ps xss -> Query ps xss xss '[]
260+insert insertion = UnsafeQuery $
261+ "INSERT " <> renderInsertion insertion <> ";"