-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | postgresql-tx interfacing for use with postgresql-query. -- -- Please see the README on GitHub at -- https://github.com/simspace/postgresql-tx#readme @package postgresql-tx-query @version 0.3.0.0 module Database.PostgreSQL.Tx.Query.Internal.Reexport -- | The 1-tuple type or single-value "collection". -- -- This type is structurally equivalent to the Identity type, but -- its intent is more about serving as the anonymous 1-tuple type missing -- from Haskell for attaching typeclass instances. -- -- Parameter usage example: -- --
--   encodeSomething (Only (42::Int))
--   
-- -- Result usage example: -- --
--   xs <- decodeSomething
--   forM_ xs $ \(Only id) -> {- ... -}
--   
newtype Only a Only :: a -> Only a [fromOnly] :: Only a -> a newtype Oid Oid :: CUInt -> Oid pgSelectCount :: forall m a q. (Entity a, MonadPostgres m, MonadLogger m, MonadFail m, ToSqlBuilder q) => Proxy a -> q -> m Integer -- | Select count of entities with given query -- --
--   activeUsers :: Handler Integer
--   activeUsers = do
--       pgSelectCount (Proxy :: Proxy User)
--           [sqlExp|WHERE active = #{True}|]
--   
-- -- Executes arbitrary query and parses it as entities and their ids pgQueryEntities :: (ToSqlBuilder q, MonadPostgres m, MonadLogger m, Entity a, FromRow a, FromField (EntityId a)) => q -> m [Ent a] -- | Update entity using ToMarkedRow instanced value. Requires -- Proxy while EntityId is not a data type. -- --
--   fixUser :: Text -> EntityId User -> Handler ()
--   fixUser username uid = do
--       pgGetEntity uid
--           >>= maybe notFound run
--     where
--       run user =
--           pgUpdateEntity uid
--           $ MR [("active", mkValue True)
--                 ("name", mkValue username)]
--   
-- -- Returns True if record was actually updated and False if -- there was not row with such id (or was more than 1, in fact) pgUpdateEntity :: forall a b m. (ToMarkedRow b, Entity a, MonadPostgres m, MonadLogger m, ToField (EntityId a), Functor m, Typeable a, Typeable b) => EntityId a -> b -> m Bool -- | Delete entity. -- --
--   rmUser :: EntityId User -> Handler ()
--   rmUser uid = do
--       pgDeleteEntity uid
--   
-- -- Return True if row was actually deleted. pgDeleteEntity :: (Entity a, MonadPostgres m, MonadLogger m, ToField (EntityId a), Functor m) => EntityId a -> m Bool -- | Insert many entities without returning list of id like -- pgInsertManyEntitiesId does pgInsertManyEntities :: (Entity a, MonadPostgres m, MonadLogger m, ToRow a) => [a] -> m Int64 -- | Same as pgInsertEntity but insert many entities at one action. -- Returns list of id's of inserted entities pgInsertManyEntitiesId :: (Entity a, MonadPostgres m, MonadLogger m, ToRow a, FromField (EntityId a)) => [a] -> m [EntityId a] -- | Get entity by some fields constraint -- --
--   getUser :: UserName -> Handler User
--   getUser name = do
--       pgGetEntityBy
--           (MR [("name", mkValue name),
--                ("active", mkValue True)])
--           >>= maybe notFound return
--   
-- -- The query here will be like -- --
--   pgQuery [sqlExp|SELECT id, name, phone ... FROM users WHERE name = {True}|]
--   
pgGetEntityBy :: forall m a b. (Entity a, MonadPostgres m, MonadLogger m, ToMarkedRow b, FromField (EntityId a), FromRow a, Functor m) => b -> m (Maybe (Ent a)) -- | Select entity by id -- --
--   getUser :: EntityId User ->  Handler User
--   getUser uid = do
--       pgGetEntity uid
--           >>= maybe notFound return
--   
pgGetEntity :: forall m a. (ToField (EntityId a), Entity a, FromRow a, MonadPostgres m, MonadLogger m, Functor m) => EntityId a -> m (Maybe a) -- | Select entities by condition formed from MarkedRow. Usefull -- function when you know pgSelectEntitiesBy :: forall a m b. (Functor m, MonadPostgres m, MonadLogger m, Entity a, ToMarkedRow b, FromRow a, FromField (EntityId a)) => b -> m [Ent a] -- | Same as pgSelectEntities but do not select id pgSelectJustEntities :: (Functor m, MonadPostgres m, MonadLogger m, Entity a, FromRow a, ToSqlBuilder q) => (FN -> FN) -> q -> m [a] -- | Select entities as pairs of (id, entity). -- --
--   handler :: Handler [Ent a]
--   handler = do
--       now <- liftIO getCurrentTime
--       let back = addUTCTime (days  (-7)) now
--       pgSelectEntities id
--           [sqlExp|WHERE created BETWEEN #{now} AND #{back}
--                  ORDER BY created|]
--   
--   handler2 :: Text -> Handler [Ent Foo]
--   handler2 fvalue = do
--       pgSelectEntities ("t"<>)
--           [sqlExp|AS t INNER JOIN table2 AS t2
--                   ON t.t2_id = t2.id
--                   WHERE t.field = #{fvalue}
--                   ORDER BY t2.field2|]
--      -- Here the query will be: SELECT ... FROM tbl AS t INNER JOIN ...
--   
pgSelectEntities :: (Functor m, MonadPostgres m, MonadLogger m, Entity a, FromRow a, ToSqlBuilder q, FromField (EntityId a)) => (FN -> FN) -> q -> m [Ent a] -- | Insert new entity and return it's id pgInsertEntity :: forall a m. (MonadPostgres m, MonadLogger m, MonadFail m, Entity a, ToRow a, FromField (EntityId a)) => a -> m (EntityId a) -- | Same as insertEntity but generates query to insert many queries -- at same time -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> instance ToRow Foo where { toRow Foo{..} = [toField fName, toField fSize] }
--   
--   >>> runSqlBuilder con $ insertManyEntities $ NL.fromList [Foo "meter" 1, Foo "table" 2, Foo "earth" 151930000000]
--   "INSERT INTO \"foo\" (\"name\",\"size\") VALUES ('meter',1),('table',2),('earth',151930000000)"
--   
insertManyEntities :: (Entity a, ToRow a) => NonEmpty a -> SqlBuilder -- | Generates INSERT INTO query for any instance of Entity -- and ToRow -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> instance ToRow Foo where { toRow Foo{..} = [toField fName, toField fSize] }
--   
--   >>> runSqlBuilder con $ insertEntity $ Foo "Enterprise" 910
--   "INSERT INTO \"foo\" (\"name\", \"size\") VALUES ('Enterprise', 910)"
--   
insertEntity :: (Entity a, ToRow a) => a -> SqlBuilder -- | Convert entity instance to marked row to perform inserts updates and -- same stuff -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> instance ToRow Foo where { toRow Foo{..} = [toField fName, toField fSize] }
--   
--   >>> runSqlBuilder con $ mrToBuilder ", " $ entityToMR $ Foo "Enterprise" 610
--   " \"name\" = 'Enterprise' ,  \"size\" = 610 "
--   
entityToMR :: (Entity a, ToRow a) => a -> MarkedRow -- | Generates SELECT FROM WHERE query with most used conditions -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> runSqlBuilder con $ selectEntitiesBy id (Proxy :: Proxy Foo) $ MR []
--   "SELECT \"name\", \"size\" FROM \"foo\""
--   
-- --
--   >>> runSqlBuilder con $ selectEntitiesBy id (Proxy :: Proxy Foo) $ MR [("name", mkValue "fooname")]
--   "SELECT \"name\", \"size\" FROM \"foo\" WHERE  \"name\" = 'fooname' "
--   
-- --
--   >>> runSqlBuilder con $ selectEntitiesBy id (Proxy :: Proxy Foo) $ MR [("name", mkValue "fooname"), ("size", mkValue 10)]
--   "SELECT \"name\", \"size\" FROM \"foo\" WHERE  \"name\" = 'fooname' AND \"size\" = 10 "
--   
selectEntitiesBy :: (Entity a, ToMarkedRow b) => ([FN] -> [FN]) -> Proxy a -> b -> SqlBuilder -- | Generate SELECT query string for entity -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> runSqlBuilder con $ selectEntity (entityFieldsId id) (Proxy :: Proxy Foo)
--   "SELECT \"id\", \"name\", \"size\" FROM \"foo\""
--   
-- --
--   >>> runSqlBuilder con $ selectEntity (entityFieldsId ("f"<>)) (Proxy :: Proxy Foo)
--   "SELECT \"f\".\"id\", \"f\".\"name\", \"f\".\"size\" FROM \"foo\""
--   
-- --
--   >>> runSqlBuilder con $ selectEntity (entityFields id id) (Proxy :: Proxy Foo)
--   "SELECT \"name\", \"size\" FROM \"foo\""
--   
selectEntity :: Entity a => (Proxy a -> SqlBuilder) -> Proxy a -> SqlBuilder -- | Same as entityFields but prefixes list of names with id -- field. This is shorthand function for often usage. -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> runSqlBuilder con $ entityFieldsId id (Proxy :: Proxy Foo)
--   "\"id\", \"name\", \"size\""
--   
-- --
--   >>> runSqlBuilder con $ entityFieldsId ("f"<>) (Proxy :: Proxy Foo)
--   "\"f\".\"id\", \"f\".\"name\", \"f\".\"size\""
--   
entityFieldsId :: Entity a => (FN -> FN) -> Proxy a -> SqlBuilder -- | Build entity fields -- --
--   >>> data Foo = Foo { fName :: Text, fSize :: Int }
--   
--   >>> instance Entity Foo where {newtype EntityId Foo = FooId Int ; fieldNames _ = ["name", "size"] ; tableName _ = "foo"}
--   
--   >>> runSqlBuilder con $ entityFields id id (Proxy :: Proxy Foo)
--   "\"name\", \"size\""
--   
-- --
--   >>> runSqlBuilder con $ entityFields ("id":) id (Proxy :: Proxy Foo)
--   "\"id\", \"name\", \"size\""
--   
-- --
--   >>> runSqlBuilder con $ entityFields (\l -> ("id":l) ++ ["created"]) id (Proxy :: Proxy Foo)
--   "\"id\", \"name\", \"size\", \"created\""
--   
-- --
--   >>> runSqlBuilder con $ entityFields id ("f"<>) (Proxy :: Proxy Foo)
--   "\"f\".\"name\", \"f\".\"size\""
--   
-- --
--   >>> runSqlBuilder con $ entityFields ("f.id":) ("f"<>) (Proxy :: Proxy Foo)
--   "\"f\".\"id\", \"f\".\"name\", \"f\".\"size\""
--   
entityFields :: Entity a => ([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder -- | Perform repsert of the same row, first trying "update where" then -- "insert" with concatenated fields. Which means that if you run -- --
--   pgRepsertRow "emails" (MR [("user_id", mkValue uid)]) (MR [("email", mkValue email)])
--   
-- -- Then firstly will be performed -- --
--   UPDATE "emails" SET email = 'foo@bar.com' WHERE "user_id" = 1234
--   
-- -- And if no one row is affected (which is returned by pgExecute), -- then -- --
--   INSERT INTO "emails" ("user_id", "email") VALUES (1234, 'foo@bar.com')
--   
-- -- will be performed pgRepsertRow :: (MonadPostgres m, MonadLogger m, ToMarkedRow wrow, ToMarkedRow urow) => FN -> wrow -> urow -> m () -- | Calls sequently deriveFromRow deriveToRow -- deriveEntity. E.g. code like this: -- --
--   data Agent = Agent
--       { aName          :: !Text
--       , aAttributes    :: !HStoreMap
--       , aLongWeirdName :: !Int
--       } deriving (Ord, Eq, Show)
--   
--   $(deriveEverything
--     def { eoIdType        = ''Id
--         , eoTableName     = textFN . toUnderscore'
--         , eoColumnNames   = textFN . toUnderscore' . drop 1
--         , eoDeriveClasses =
--           [''Show, ''Read, ''Ord, ''Eq
--           , ''FromField, ''ToField, ''PathPiece]
--         }
--     ''Agent )
--   
-- -- will generate that: -- --
--   instance ToRow Agent where
--       toRow (Agent a_aE3w a_aE3x a_aE3y)
--           = [toField a_aE3w, toField a_aE3x, toField a_aE3y]
--   instance FromRow Agent where
--     fromRow
--         = Agent $ Database.PostgreSQL.Simple.FromRow.field
--           * Database.PostgreSQL.Simple.FromRow.field
--           * Database.PostgreSQL.Simple.FromRow.field
--   instance Database.PostgreSQL.Query.Entity Agent where
--       newtype EntityId Agent
--           = AgentId {getAgentId :: Id}
--           deriving (Show, Read, Ord, Eq, FromField, ToField, PathPiece)
--       tableName _ = "agent"
--       fieldNames _ = ["name", "attributes", "long_weird_name"]
--   type AgentId = EntityId Agent
--   
deriveEverything :: EntityOptions -> Name -> Q [Dec] -- | Derives instance for Entity using type name and field names. -- Also generates type synonim for ID. E.g. code like this: -- --
--   data Agent = Agent
--       { aName          :: !Text
--       , aAttributes    :: !HStoreMap
--       , aLongWeirdName :: !Int
--       } deriving (Ord, Eq, Show)
--   
--   $(deriveEntity
--     def { eoIdType        = ''Id
--         , eoTableName     = textFN . toUnderscore'
--         , eoColumnNames   = textFN . toUnderscore' . drop 1
--         , eoDeriveClasses =
--           [''Show, ''Read, ''Ord, ''Eq
--           , ''FromField, ''ToField, ''PathPiece]
--         }
--     ''Agent )
--   
-- -- Will generate code like this: -- --
--   instance Database.PostgreSQL.Query.Entity Agent where
--       newtype EntityId Agent
--           = AgentId {getAgentId :: Id}
--           deriving (Show, Read, Ord, Eq, FromField, ToField, PathPiece)
--       tableName _ = "agent"
--       fieldNames _ = ["name", "attributes", "long_weird_name"]
--   type AgentId = EntityId Agent
--   
-- -- So, you dont need to write it by hands any more. -- -- NOTE: toUnderscore is from package inflections here deriveEntity :: EntityOptions -> Name -> Q [Dec] -- | Options for deriving Entity data EntityOptions EntityOptions :: (Text -> FN) -> (Text -> FN) -> [Name] -> Name -> EntityOptions -- | Type name to table name converter [eoTableName] :: EntityOptions -> Text -> FN -- | Record field to column name converter [eoColumnNames] :: EntityOptions -> Text -> FN -- | Typeclasses to derive for Id [eoDeriveClasses] :: EntityOptions -> [Name] -- | Base type for Id [eoIdType] :: EntityOptions -> Name -- | Id type for this entity data family EntityId a -- | Auxiliary typeclass for data types which can map to rows of some -- table. This typeclass is used inside functions like -- pgSelectEntities to generate queries. class Entity a where { -- | Id type for this entity data family EntityId a; } -- | Table name of this entity tableName :: Entity a => Proxy a -> FN -- | Field names without id and created. The order of field -- names must match with order of fields in ToRow and -- FromRow instances of this type. fieldNames :: Entity a => Proxy a -> [FN] -- | Entity with it's id type Ent a = (EntityId a, a) -- | If your monad have instance of HasPostgres you maybe dont need -- this function, unless your instance use withPGPool which -- acquires connection from pool for each query. If you want to run -- sequence of queries using same connection you need this function launchPG :: HasPostgres m => PgMonadT m a -> m a runPgMonadT :: Connection -> PgMonadT m a -> m a -- | Turns marked row to query intercalating it with other builder -- --
--   >>> runSqlBuilder c $ mrToBuilder "AND" $ MR [("name", mkValue "petr"), ("email", mkValue "foo@bar.com")]
--   " \"name\" = 'petr' AND \"email\" = 'foo@bar.com' "
--   
mrToBuilder :: SqlBuilder -> MarkedRow -> SqlBuilder -- | Single field to FN -- --
--   >>> textFN "hello"
--   FN ["hello"]
--   
-- --
--   >>> textFN "user.name"
--   FN ["user.name"]
--   
-- -- Note that it does not split string to parts by point like instance of -- IsString does textFN :: Text -> FN -- | Marked row is list of pairs of field name and some sql expression. -- Used to generate queries like: -- --
--   name = name AND size = 10 AND length = 20
--   
-- -- or -- --
--   UPDATE tbl SET name = name, size = 10, lenght = 20
--   
newtype MarkedRow MR :: [(FN, SqlBuilder)] -> MarkedRow [unMR] :: MarkedRow -> [(FN, SqlBuilder)] class ToMarkedRow a -- | generate list of pairs (field name, field value) toMarkedRow :: ToMarkedRow a => a -> MarkedRow type MonadPostgres (m :: Type -> Type) = (HasPostgres m, MonadLogger m) -- | Instances of this typeclass can acquire connection and pass it to -- computation. It can be reader of pool of connections or just reader of -- connection class MonadBase IO m => HasPostgres (m :: Type -> Type) withPGConnection :: HasPostgres m => (Connection -> m a) -> m a -- | Empty typeclass signing monad in which transaction is safe. i.e. -- PgMonadT have this instance, but some other monad giving -- connection from e.g. connection pool is not. class TransactionSafe (m :: Type -> Type) -- | Reader of connection. Has instance of HasPostgres. So if you -- have a connection you can run queries in this monad using -- runPgMonadT. Or you can use this transformer to run sequence of -- queries using same connection with launchPG. newtype PgMonadT (m :: Type -> Type) a PgMonadT :: ReaderT Connection m a -> PgMonadT (m :: Type -> Type) a [unPgMonadT] :: PgMonadT (m :: Type -> Type) a -> ReaderT Connection m a -- | Special constructor to perform old-style query interpolation data Qp Qp :: Query -> row -> Qp -- | type to put and get from db inet and cidr typed -- postgresql fields. This should be in postgresql-simple in fact. newtype InetText InetText :: Text -> InetText [unInetText] :: InetText -> Text -- | Dot-separated field name. Each element in nested list will be properly -- quoted and separated by dot. It also have instance of -- ToSqlBuilder and IsString so you can: -- --
--   >>> let a = "hello" :: FN
--   
--   >>> a
--   FN ["hello"]
--   
-- --
--   >>> let b = "user.name" :: FN
--   
--   >>> b
--   FN ["user","name"]
--   
-- --
--   >>> let n = "u.name" :: FN
--   
--   >>> runSqlBuilder c $ toSqlBuilder n
--   "\"u\".\"name\""
--   
-- --
--   >>> ("user" <> "name") :: FN
--   FN ["user","name"]
--   
-- --
--   >>> let a = "name" :: FN
--   
--   >>> let b = "email" :: FN
--   
--   >>> runSqlBuilder c [sqlExp|^{"u" <> a} = 'name', ^{"e" <> b} = 'email'|]
--   "\"u\".\"name\" = 'name', \"e\".\"email\" = 'email'"
--   
newtype FN FN :: [Text] -> FN -- | Just like sqlExpEmbed but uses pattern instead of file name. -- So, code -- --
--   let query = $(sqlExpFile "foo/bar")
--   
-- -- is just the same as -- --
--   let query = $(sqlExpEmbed "sqlfoobar.sql")
--   
-- -- This function inspired by Yesod's widgetFile sqlExpFile :: String -> Q Exp -- | Embed sql template and perform interpolation -- --
--   let name = "name"
--       foo = "bar"
--       query = $(sqlExpEmbed "sqlfoobar.sql") -- using foo and bar inside
--   
sqlExpEmbed :: String -> Q Exp -- | Build expression of type SqlBuilder from SQL query with -- interpolation sqlQExp :: String -> Q Exp -- | Removes sequential occurencies of RLit constructors. Also -- removes commentaries and squash sequences of spaces to single space -- symbol squashRope :: [Rope] -> [Rope] ropeParser :: Parser [Rope] parseRope :: String -> [Rope] -- | Maybe the main feature of all library. Quasiquoter which builds -- SqlBuilder from string query. Removes line comments and block -- comments (even nested) and sequences of spaces. Correctly works -- handles string literals and quoted identifiers. Here is examples of -- usage -- --
--   >>> let name = "name"
--   
--   >>> let val = "some 'value'"
--   
--   >>> runSqlBuilder c [sqlExp|SELECT * FROM tbl WHERE ^{mkIdent name} = #{val}|]
--   "SELECT * FROM tbl WHERE \"name\" = 'some ''value'''"
--   
-- -- And more comples example: -- --
--   >>> let name = Just "name"
--   
--   >>> let size = Just 10
--   
--   >>> let active = Nothing :: Maybe Bool
--   
--   >>> let condlist = catMaybes [ fmap (\a -> [sqlExp|name = #{a}|]) name, fmap (\a -> [sqlExp|size = #{a}|]) size, fmap (\a -> [sqlExp|active = #{a}|]) active]
--   
--   >>> let cond = if L.null condlist then mempty else [sqlExp| WHERE ^{mconcat $ L.intersperse " AND " $ condlist} |]
--   
--   >>> runSqlBuilder c [sqlExp|SELECT *   FROM tbl ^{cond} -- line comment|]
--   "SELECT * FROM tbl  WHERE name = 'name' AND size = 10  "
--   
sqlExp :: QuasiQuoter -- | Internal type. Result of parsing sql string data Rope -- | Part of raw sql RLit :: Text -> Rope -- | Sql comment RComment :: Text -> Rope -- | Sequence of spaces RSpaces :: Int -> Rope -- | String with haskell expression inside #{..} or #?{..} RInt :: FieldOption -> Text -> Rope -- | String with haskell expression inside ^{..} RPaste :: Text -> Rope -- | derives ToRow instance for datatype like -- --
--   data Entity = Entity
--                 { eField :: Text
--                 , eField2 :: Int
--                 , efield3 :: Bool }
--   
-- -- it will derive instance like that: -- --
--   instance ToRow Entity where
--        toRow (Entity e1 e2 e3) =
--            [ toField e1
--            , toField e2
--            , toField e3 ]
--   
deriveToRow :: Name -> Q [Dec] -- | Derive FromRow instance. i.e. you have type like that -- --
--   data Entity = Entity
--                 { eField :: Text
--                 , eField2 :: Int
--                 , efield3 :: Bool }
--   
-- -- then deriveFromRow will generate this instance: instance -- FromRow Entity where -- --
--   instance FromRow Entity where
--       fromRow = Entity
--                 <$> field
--                 <*> field
--                 <*> field
--   
-- -- Datatype must have just one constructor with arbitrary count of fields deriveFromRow :: Name -> Q [Dec] -- | derives FromField and ToField instances for a sum-type -- enum like -- --
--   data Entity = Red | Green | Blue
--   
derivePgEnum :: InflectorFunc -> Name -> DecsQ -- | Function to transform constructor name into its PG enum conterpart. type InflectorFunc = String -> String -- | Things which always can be transformed to SqlBuilder class ToSqlBuilder a toSqlBuilder :: ToSqlBuilder a => a -> SqlBuilder -- | Unsafe function to make SqlBuilder from arbitrary ByteString. Does not -- perform any checks. Dont use it directly in your code unless you know -- what you are doing. sqlBuilderFromByteString :: ByteString -> SqlBuilder -- | Lift pure bytestring builder to SqlBuilder. This is unsafe to -- use directly in your code. sqlBuilderPure :: Builder -> SqlBuilder sqlBuilderFromField :: ToField a => FieldOption -> a -> SqlBuilder -- | Shorthand function to convert single masked field value (which should -- not be shown in log) mkMaskedValue :: ToField a => a -> SqlBuilder -- | Shorthand function to convert single field value to builder mkValue :: ToField a => a -> SqlBuilder -- | Typed synonym of mempty emptyB :: SqlBuilder -- | Returns query string with log bytestring runSqlBuilder :: Connection -> LogMasker -> SqlBuilder -> IO (Query, ByteString) -- | Builder wich can be effectively concatenated. Requires -- Connection inside for string quoting implemented in -- libpq. Builds two strings: query string and log string which -- may differ. newtype SqlBuilder SqlBuilder :: (Connection -> LogMasker -> IO SqlBuilderResult) -> SqlBuilder [sqlBuild] :: SqlBuilder -> Connection -> LogMasker -> IO SqlBuilderResult -- | Masks fields which size is bigger than given argument in bytes. hugeFieldsMasker :: Int -> LogMasker -- | Simply replaces masked fields with placeholder. defaultLogMasker :: LogMasker -- | Function modifying query parameter value before pasting it to log. type LogMasker = FieldOption -> Builder -> Builder builderResultPure :: Builder -> SqlBuilderResult -- | Result if SqlBuilder. Contains separated builder for query and log. data SqlBuilderResult SqlBuilderResult :: Builder -> Builder -> SqlBuilderResult [sbQueryString] :: SqlBuilderResult -> Builder [sbLogString] :: SqlBuilderResult -> Builder -- | Option for field instructing LogMasker what to do with field -- when logging data FieldOption -- | Do nothing. Field should be pasted as is FieldDefault :: FieldOption -- | Mask field in logs with placeholder. FieldMasked :: FieldOption -- | Represents a VALUES table literal, usable as an alternative -- to executeMany and returning. The main advantage is that -- you can parametrize more than just a single VALUES -- expression. For example, here's a query to insert a thing into one -- table and some attributes of that thing into another, returning the -- new id generated by the database: -- --
--   query c [sql|
--       WITH new_thing AS (
--         INSERT INTO thing (name) VALUES (?) RETURNING id
--       ), new_attributes AS (
--         INSERT INTO thing_attributes
--            SELECT new_thing.id, attrs.*
--              FROM new_thing JOIN ? attrs ON TRUE
--       ) SELECT * FROM new_thing
--    |] ("foo", Values [  "int4", "text"    ]
--                      [ ( 1    , "hello" )
--                      , ( 2    , "world" ) ])
--   
-- -- (Note this example uses writable common table expressions, which were -- added in PostgreSQL 9.1) -- -- The second parameter gets expanded into the following SQL syntax: -- --
--   (VALUES (1::"int4",'hello'::"text"),(2,'world'))
--   
-- -- When the list of attributes is empty, the second parameter expands to: -- --
--   (VALUES (null::"int4",null::"text") LIMIT 0)
--   
-- -- By contrast, executeMany and returning don't issue -- the query in the empty case, and simply return 0 and -- [] respectively. This behavior is usually correct given their -- intended use cases, but would certainly be wrong in the example above. -- -- The first argument is a list of postgresql type names. Because this is -- turned into a properly quoted identifier, the type name is case -- sensitive and must be as it appears in the pg_type table. -- Thus, you must write timestamptz instead of timestamp -- with time zone, int4 instead of integer or -- serial, _int8 instead of bigint[], -- etcetera. -- -- You may omit the type names, however, if you do so the list of values -- must be non-empty, and postgresql must be able to infer the types of -- the columns from the surrounding context. If the first condition is -- not met, postgresql-simple will throw an exception without issuing the -- query. In the second case, the postgres server will return an error -- which will be turned into a SqlError exception. -- -- See https://www.postgresql.org/docs/9.5/static/sql-values.html -- for more information. data Values a Values :: [QualifiedIdentifier] -> [a] -> Values a -- | A composite type to parse your custom data structures without having -- to define dummy newtype wrappers every time. -- --
--   instance FromRow MyData where ...
--   
-- --
--   instance FromRow MyData2 where ...
--   
-- -- then I can do the following for free: -- --
--   res <- query' c "..."
--   forM res $ \(MyData{..} :. MyData2{..}) -> do
--     ....
--   
data h :. t (:.) :: h -> t -> (:.) h t infixr 3 :. infixr 3 :. -- | Wrap a list for use as a PostgreSQL array. newtype PGArray a PGArray :: [a] -> PGArray a [fromPGArray] :: PGArray a -> [a] -- | Wrap a list of values for use in an IN clause. Replaces a -- single "?" character with a parenthesized list of rendered -- values. -- -- Example: -- --
--   query c "select * from whatever where id in ?" (Only (In [3,4,5]))
--   
-- -- Note that In [] expands to (null), which works as -- expected in the query above, but evaluates to the logical null value -- on every row instead of TRUE. This means that changing the -- query above to ... id NOT in ? and supplying the empty list -- as the parameter returns zero rows, instead of all of them as one -- would expect. -- -- Since postgresql doesn't seem to provide a syntax for actually -- specifying an empty list, which could solve this completely, there are -- two workarounds particularly worth mentioning, namely: -- --
    --
  1. Use postgresql-simple's Values type instead, which can -- handle the empty case correctly. Note however that while specifying -- the postgresql type "int4" is mandatory in the empty case, -- specifying the haskell type Values (Only Int) would not -- normally be needed in realistic use cases.
    query c "select * from
    --   whatever where id not in ?" (Only (Values ["int4"] [] :: Values (Only
    --   Int)))
  2. --
  3. Use sql's COALESCE operator to turn a logical -- null into the correct boolean. Note however that the correct -- boolean depends on the use case:
    query c "select * from whatever
    --   where coalesce(id NOT in ?, TRUE)" (Only (In [] :: In
    --   [Int]))
    query c "select * from whatever where coalesce(id IN
    --   ?, FALSE)" (Only (In [] :: In [Int]))
    Note that at as of -- PostgreSQL 9.4, the query planner cannot see inside the -- COALESCE operator, so if you have an index on id -- then you probably don't want to write the last example with -- COALESCE, which would result in a table scan. There are -- further caveats if id can be null or you want null treated -- sensibly as a component of IN or NOT IN.
  4. --
newtype In a In :: a -> In a -- | A query string. This type is intended to make it difficult to -- construct a SQL query by concatenating string fragments, as that is an -- extremely common way to accidentally introduce SQL injection -- vulnerabilities into an application. -- -- This type is an instance of IsString, so the easiest way to -- construct a query is to enable the OverloadedStrings language -- extension and then simply write the query in double quotes. -- --
--   {-# LANGUAGE OverloadedStrings #-}
--   
--   import Database.PostgreSQL.Simple
--   
--   q :: Query
--   q = "select ?"
--   
-- -- The underlying type is a ByteString, and literal Haskell -- strings that contain Unicode characters will be correctly transformed -- to UTF-8. newtype Query Query :: ByteString -> Query [fromQuery] :: Query -> ByteString -- | A type that may be used as a single parameter to a SQL query. class ToField a -- | Prepare a value for substitution into a query string. toField :: ToField a => a -> Action -- | A collection type that can be turned into a list of rendering -- Actions. -- -- Instances should use the toField method of the ToField -- class to perform conversion of each element of the collection. -- -- You can derive ToRow for your data type using GHC generics, -- like this: -- --
--   {-# LANGUAGE DeriveAnyClass #-}
--   {-# LANGUAGE DeriveGeneric  #-}
--   
--   import GHC.Generics (Generic)
--   import Database.PostgreSQL.Simple (ToRow)
--   
--   data User = User { name :: String, fileQuota :: Int }
--     deriving (Generic, ToRow)
--   
-- -- Note that this only works for product types (e.g. records) and does -- not support sum types or recursive types. class ToRow a toRow :: ToRow a => a -> [Action] data ConnectInfo ConnectInfo :: String -> Word16 -> String -> String -> String -> ConnectInfo [connectHost] :: ConnectInfo -> String [connectPort] :: ConnectInfo -> Word16 [connectUser] :: ConnectInfo -> String [connectPassword] :: ConnectInfo -> String [connectDatabase] :: ConnectInfo -> String data Connection -- | Default information for setting up a connection. -- -- Defaults are as follows: -- -- -- -- Use as in the following example: -- --
--   connect defaultConnectInfo { connectHost = "db.example.com" }
--   
defaultConnectInfo :: ConnectInfo -- | Connect with the given username to the given database. Will throw an -- exception if it cannot connect. connect :: ConnectInfo -> IO Connection -- | Attempt to make a connection based on a libpq connection string. See -- https://www.postgresql.org/docs/9.5/static/libpq-connect.html#LIBPQ-CONNSTRING -- for more information. Also note that environment variables also affect -- parameters not provided, parameters provided as the empty string, and -- a few other things; see -- https://www.postgresql.org/docs/9.5/static/libpq-envars.html -- for details. Here is an example with some of the most commonly used -- parameters: -- --
--   host='db.somedomain.com' port=5432 ...
--   
-- -- This attempts to connect to db.somedomain.com:5432. Omitting -- the port will normally default to 5432. -- -- On systems that provide unix domain sockets, omitting the host -- parameter will cause libpq to attempt to connect via unix domain -- sockets. The default filesystem path to the socket is constructed from -- the port number and the DEFAULT_PGSOCKET_DIR constant defined -- in the pg_config_manual.h header file. Connecting via unix -- sockets tends to use the peer authentication method, which is -- very secure and does not require a password. -- -- On Windows and other systems without unix domain sockets, omitting the -- host will default to localhost. -- --
--   ... dbname='postgres' user='postgres' password='secret \' \\ pw'
--   
-- -- This attempts to connect to a database named postgres with -- user postgres and password secret ' \ pw. Backslash -- characters will have to be double-quoted in literal Haskell strings, -- of course. Omitting dbname and user will both -- default to the system username that the client process is running as. -- -- Omitting password will default to an appropriate password -- found in the pgpass file, or no password at all if a matching -- line is not found. The path of the pgpass file may be -- specified by setting the PGPASSFILE environment variable. See -- https://www.postgresql.org/docs/9.5/static/libpq-pgpass.html -- for more information regarding this file. -- -- As all parameters are optional and the defaults are sensible, the -- empty connection string can be useful for development and exploratory -- use, assuming your system is set up appropriately. -- -- On Unix, such a setup would typically consist of a local postgresql -- server listening on port 5432, as well as a system user, database -- user, and database sharing a common name, with permissions granted to -- the user on the database. -- -- On Windows, in addition you will either need pg_hba.conf to -- specify the use of the trust authentication method for the -- connection, which may not be appropriate for multiuser or production -- machines, or you will need to use a pgpass file with the -- password or md5 authentication methods. -- -- See -- https://www.postgresql.org/docs/9.5/static/client-authentication.html -- for more information regarding the authentication process. -- -- SSL/TLS will typically "just work" if your postgresql server supports -- or requires it. However, note that libpq is trivially vulnerable to a -- MITM attack without setting additional SSL connection parameters. In -- particular, sslmode needs to be set to require, -- verify-ca, or verify-full in order to perform -- certificate validation. When sslmode is require, -- then you will also need to specify a sslrootcert file, -- otherwise no validation of the server's identity will be performed. -- Client authentication via certificates is also possible via the -- sslcert and sslkey parameters. See -- https://www.postgresql.org/docs/9.5/static/libpq-ssl.html for -- detailed information regarding libpq and SSL. connectPostgreSQL :: ByteString -> IO Connection -- | A type that may be converted from a SQL type. class FromField a -- | Convert a SQL value to a Haskell value. -- -- Returns a list of exceptions if the conversion fails. In the case of -- library instances, this will usually be a single ResultError, -- but may be a UnicodeException. -- -- Note that retaining any reference to the Field argument causes -- the entire LibPQ.Result to be retained. Thus, -- implementations of fromField should return results that do not -- refer to this value after the result have been evaluated to WHNF. -- -- Note that as of postgresql-simple-0.4.0.0, the -- ByteString value has already been copied out of the -- LibPQ.Result before it has been passed to -- fromField. This is because for short strings, it's cheaper to -- copy the string than to set up a finalizer. fromField :: FromField a => FieldParser a -- | A collection type that can be converted from a sequence of fields. -- Instances are provided for tuples up to 10 elements and lists of any -- length. -- -- Note that instances can be defined outside of postgresql-simple, which -- is often useful. For example, here's an instance for a user-defined -- pair: -- --
--   data User = User { name :: String, fileQuota :: Int }
--   
--   instance FromRow User where
--       fromRow = User <$> field <*> field
--   
-- -- The number of calls to field must match the number of fields -- returned in a single row of the query result. Otherwise, a -- ConversionFailed exception will be thrown. -- -- You can also derive FromRow for your data type using GHC -- generics, like this: -- --
--   {-# LANGUAGE DeriveAnyClass #-}
--   {-# LANGUAGE DeriveGeneric  #-}
--   
--   import GHC.Generics (Generic)
--   import Database.PostgreSQL.Simple (FromRow)
--   
--   data User = User { name :: String, fileQuota :: Int }
--     deriving (Generic, FromRow)
--   
-- -- Note that this only works for product types (e.g. records) and does -- not support sum types or recursive types. -- -- Note that field evaluates its result to WHNF, so the caveats -- listed in mysql-simple and very early versions of postgresql-simple no -- longer apply. Instead, look at the caveats associated with -- user-defined implementations of fromField. class FromRow a fromRow :: FromRow a => RowParser a newtype HStoreMap HStoreMap :: Map Text Text -> HStoreMap [fromHStoreMap] :: HStoreMap -> Map Text Text newtype HStoreList HStoreList :: [(Text, Text)] -> HStoreList [fromHStoreList] :: HStoreList -> [(Text, Text)] -- | Represents escape text, ready to be the key or value to a hstore value data HStoreText class ToHStoreText a toHStoreText :: ToHStoreText a => a -> HStoreText -- | Represents valid hstore syntax. data HStoreBuilder class ToHStore a toHStore :: ToHStore a => a -> HStoreBuilder hstore :: (ToHStoreText a, ToHStoreText b) => a -> b -> HStoreBuilder parseHStoreList :: ByteString -> Either String HStoreList defaultTransactionMode :: TransactionMode -- | Of the four isolation levels defined by the SQL standard, these are -- the three levels distinguished by PostgreSQL as of version 9.0. See -- https://www.postgresql.org/docs/9.5/static/transaction-iso.html -- for more information. Note that prior to PostgreSQL 9.0, -- RepeatableRead was equivalent to Serializable. data IsolationLevel -- | the isolation level will be taken from PostgreSQL's per-connection -- default_transaction_isolation variable, which is initialized -- according to the server's config. The default configuration is -- ReadCommitted. DefaultIsolationLevel :: IsolationLevel ReadCommitted :: IsolationLevel RepeatableRead :: IsolationLevel Serializable :: IsolationLevel data ReadWriteMode -- | the read-write mode will be taken from PostgreSQL's per-connection -- default_transaction_read_only variable, which is initialized -- according to the server's config. The default configuration is -- ReadWrite. DefaultReadWriteMode :: ReadWriteMode ReadWrite :: ReadWriteMode ReadOnly :: ReadWriteMode data TransactionMode TransactionMode :: !IsolationLevel -> !ReadWriteMode -> TransactionMode [isolationLevel] :: TransactionMode -> !IsolationLevel [readWriteMode] :: TransactionMode -> !ReadWriteMode module Database.PostgreSQL.Tx.Query.Internal -- | Analogous to TxM but allows for IO. Useful so we can -- have instances which are required to run postgresql-query -- functions. See unsafeToPgQueryIO and unsafeFromPgQueryIO -- for converting to/from TxM. newtype UnsafePgQueryIO r a UnsafePgQueryIO :: ReaderT r IO a -> UnsafePgQueryIO r a -- | Re-export of Logger. type Logger = Logger -- | Monad type alias for running postgresql-query via -- postgresql-tx. type PgQueryM a = forall r. (PgQueryEnv r) => TxM r a -- | Runtime environment needed to run postgresql-query via -- postgresql-tx. type PgQueryEnv r = (TxEnvs '[Connection, Logger] r) :: Constraint unsafeToPgQueryIO :: HasCallStack => TxM r a -> UnsafePgQueryIO r a unsafeFromPgQueryIO :: HasCallStack => UnsafePgQueryIO r a -> TxM r a unsafeRunPgQueryTransaction :: (PgQueryEnv r, HasCallStack) => (HasCallStack => UnsafePgQueryIO r a -> UnsafePgQueryIO r a) -> r -> TxM r a -> IO a instance Control.Monad.Catch.MonadThrow (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Control.Monad.Catch.MonadMask (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Control.Monad.Catch.MonadCatch (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Database.PostgreSQL.Query.Types.TransactionSafe (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Control.Monad.Trans.Control.MonadBaseControl GHC.Types.IO (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Control.Monad.Base.MonadBase GHC.Types.IO (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Control.Monad.IO.Class.MonadIO (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance GHC.Base.Monad (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance GHC.Base.Applicative (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance GHC.Base.Functor (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Database.PostgreSQL.Tx.Query.Internal.PgQueryEnv r => Database.PostgreSQL.Query.Types.HasPostgres (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Database.PostgreSQL.Tx.Query.Internal.PgQueryEnv r => Control.Monad.Logger.MonadLogger (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) instance Database.PostgreSQL.Tx.Query.Internal.PgQueryEnv r => Control.Monad.Logger.MonadLoggerIO (Database.PostgreSQL.Tx.Query.Internal.UnsafePgQueryIO r) module Database.PostgreSQL.Tx.Query -- | Runtime environment needed to run postgresql-query via -- postgresql-tx. type PgQueryEnv r = (TxEnvs '[Connection, Logger] r) :: Constraint -- | Monad type alias for running postgresql-query via -- postgresql-tx. type PgQueryM a = forall r. (PgQueryEnv r) => TxM r a -- | Re-export of Logger. type Logger = Logger -- | Analogue of pgWithTransaction. pgWithTransaction :: (PgQueryEnv r, HasCallStack) => r -> (HasCallStack => TxM r a) -> IO a -- | Analogue of pgWithTransactionMode. pgWithTransactionMode :: (PgQueryEnv r, HasCallStack) => TransactionMode -> r -> (HasCallStack => TxM r a) -> IO a -- | Analogue of pgWithTransactionSerializable Unlike -- postgresql-query, uses shouldRetryTx to also retry -- on deadlock_detected, not just -- serialization_failure. -- -- Note that any IO that occurs inside the TxM may be -- executed multiple times. pgWithTransactionSerializable :: (PgQueryEnv r, HasCallStack) => r -> (HasCallStack => TxM r a) -> IO a -- | Analogue of pgWithTransactionModeRetry. You should generally -- prefer pgWithTransactionSerializable. -- -- Note that any IO that occurs inside the TxM may be -- executed multiple times. pgWithTransactionModeRetry :: (PgQueryEnv r, Exception e, HasCallStack) => TransactionMode -> (e -> Bool) -> r -> (HasCallStack => TxM r a) -> IO a -- | Analogue of pgWithSavepoint. pgWithSavepoint :: (HasCallStack => PgQueryM a) -> PgQueryM a -- | Analogue of pgQuery. pgQuery :: (ToSqlBuilder q, FromRow r, HasCallStack) => q -> PgQueryM [r] -- | Analogue of pgQueryWithMasker. pgQueryWithMasker :: (ToSqlBuilder q, FromRow r, HasCallStack) => LogMasker -> q -> PgQueryM [r] -- | Analogue of pgExecute. pgExecute :: (ToSqlBuilder q, HasCallStack) => q -> PgQueryM Int64 -- | Analogue of pgExecuteWithMasker. pgExecuteWithMasker :: (ToSqlBuilder q, HasCallStack) => LogMasker -> q -> PgQueryM Int64