on 35c6127 help sign in
rel8/src/Rel8/Statement/Insert.hs
89 lines 2.4 kB history raw
1{-# language DuplicateRecordFields #-}
2{-# language FlexibleContexts #-}
3{-# language GADTs #-}
4{-# language NamedFieldPuns #-}
5{-# language RecordWildCards #-}
6{-# language StandaloneKindSignatures #-}
7{-# language StrictData #-}
9module Rel8.Statement.Insert
10 ( Insert(..)
11 , insert
12 , ppInsert
13 , ppInto
14 )
15where
17-- base
18import Data.Foldable ( toList )
19import Data.Kind ( Type )
20import Prelude
22-- hasql
23import qualified Hasql.Encoders as Hasql
24import qualified Hasql.Statement as Hasql
26-- opaleye
27import qualified Opaleye.Internal.HaskellDB.Sql.Print as Opaleye
29-- pretty
30import Text.PrettyPrint ( Doc, (<+>), ($$), parens, text )
32-- rel8
33import Rel8.Query ( Query )
34import Rel8.Schema.Name ( Name, Selects, ppColumn )
35import Rel8.Schema.Table ( TableSchema(..), ppTable )
36import Rel8.Statement.OnConflict ( OnConflict, ppOnConflict )
37import Rel8.Statement.Returning ( Returning, decodeReturning, ppReturning )
38import Rel8.Statement.Select ( ppRows )
39import Rel8.Table ( Table )
40import Rel8.Table.Name ( showNames )
42-- text
43import qualified Data.Text as Text ( pack )
44import Data.Text.Encoding ( encodeUtf8 )
47-- | The constituent parts of a SQL @INSERT@ statement.
48type Insert :: Type -> Type
49data Insert a where
50 Insert :: Selects names exprs =>
51 { into :: TableSchema names
52 -- ^ Which table to insert into.
53 , rows :: Query exprs
54 -- ^ The rows to insert. This can be an arbitrary query — use
55 -- 'Rel8.values' insert a static list of rows.
56 , onConflict :: OnConflict names
57 -- ^ What to do if the inserted rows conflict with data already in the
58 -- table.
59 , returning :: Returning names a
60 -- ^ What information to return on completion.
61 }
62 -> Insert a
65ppInsert :: Insert a -> Doc
66ppInsert Insert {..} =
67 text "INSERT INTO" <+>
68 ppInto into $$
69 ppRows rows $$
70 ppOnConflict into onConflict $$
71 ppReturning into returning
74ppInto :: Table Name a => TableSchema a -> Doc
75ppInto table@TableSchema {columns} =
76 ppTable table <+>
77 parens (Opaleye.commaV ppColumn (toList (showNames columns)))
80-- | Run an 'Insert' statement.
81insert :: Insert a -> Hasql.Statement () a
82insert i@Insert {returning} = Hasql.Statement bytes params decode prepare
83 where
84 bytes = encodeUtf8 $ Text.pack sql
85 params = Hasql.noParams
86 decode = decodeReturning returning
87 prepare = False
88 sql = show doc
89 doc = ppInsert i