Skip to content

Commit

Permalink
[#5] Write some README (#14)
Browse files Browse the repository at this point in the history
* [#5] Write some README

Resolves #5

* Update src/PgNamed.hs

Co-Authored-By: Dmitrii Kovanikov <[email protected]>

* Update README.md

Co-Authored-By: Dmitrii Kovanikov <[email protected]>

* Update README.md

Co-Authored-By: Dmitrii Kovanikov <[email protected]>

* Update README.md

Co-Authored-By: Dmitrii Kovanikov <[email protected]>

* Fix after review
  • Loading branch information
vrom911 authored and Dmitrii Kovanikov committed Jul 11, 2019
1 parent 707766a commit f590551
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 20 deletions.
67 changes: 64 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,70 @@
# postgresql-simple-named

[![Build status](https://img.shields.io/travis/Holmusk/postgresql-simple-named.svg?logo=travis)](https://travis-ci.org/Holmusk/postgresql-simple-named)
[![Hackage](https://img.shields.io/hackage/v/postgresql-simple-named.svg?logo=haskell)](https://hackage.haskell.org/package/postgresql-simple-named)
[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)
[![Stackage Lts](http://stackage.org/package/postgresql-simple-named/badge/lts)](http://stackage.org/lts/package/postgresql-simple-named)
[![Stackage Nightly](http://stackage.org/package/postgresql-simple-named/badge/nightly)](http://stackage.org/nightly/package/postgresql-simple-named)
[![Build status](https://img.shields.io/travis/Holmusk/postgresql-simple-named.svg?logo=travis)](https://travis-ci.org/Holmusk/postgresql-simple-named)
[![MPL-2.0 license](https://img.shields.io/badge/license-MPL--2.0-blue.svg)](LICENSE)

This library introduces the implementation of named parameters for the
[`postgresql-simple`][pgs] library. `postgresql-simple-named` is considered to
be used along with the [`postgresql-simple`][pgs] library, so you could refer
there for the original documentation of primary functions. This package solves
exclusively one particular problem — gives the ability to use named parameters
instead of `?` in quasi-quoter queries and offers essential functions for substituting
variables in queries (`queryNamed`, `executeNamed`).

## Example

Operator `=?` binds named parameters with the corresponding values. Named
parameters inside SQL query start with the '?' character and can contain
lowercase and uppercase letters, digits and underscore. Below you can find a
basic example of how query with named parameters could look like:

```haskell
queryNamed dbConnection [sql|
SELECT
id, name, city
FROM users
WHERE name = ?nameParam
AND age = ?ageParam

Implementation of named parameters for `postgresql-simple` library
|] [ "nameParam" =? "John"
, "ageParam" =? 42
]
```

This feature can be extremely helpful when the query uses some parameters more than once:

```haskell
query dbConnection [sql|
SELECT
col1, col2
FROM my_table
WHERE id = ?
AND (? IS NULL OR id > ? )
AND (? IS NULL OR id < ? )

|] (someId, minId, minId, maxId, maxId)
```

This is how the query looks like with the `postgresql-simple` library. You can
rewrite it the following way using the `postgresql-simple-named` library:

```haskell
queryNamed dbConnection [sql|
SELECT
col1, col2
FROM my_table
WHERE id = ?someId
AND (?minId IS NULL OR id > ?minId )
AND (?maxId IS NULL OR id < ?maxId )

|] [ "someId" =? 42
, "minId" =? 1
, "maxId" =? 100
]
```

## How to build

Expand All @@ -19,3 +77,6 @@ Build the library with either `cabal new-build` or `stack build`.
docker run -p 5432\:5432 -e POSTGRES_USER=postgres -e POSTGRES_DB=pg_named postgres\:10.5-alpine
```
* Run tests using `cabal new-test` or `stack test`


[pgs]: https://hackage.haskell.org/package/postgresql-simple
6 changes: 3 additions & 3 deletions postgresql-simple-named.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: postgresql-simple-named
version: 0.0.0.0
synopsis: Implementation of named parameters for `postgresql-simple` library
description:
Implementation of named parameters for `postgresql-simple` library.
Implementation of named parameters for @postgresql-simple@ library.
.
Here is an exaple of how it could be used in your code:
.
Expand All @@ -21,8 +21,8 @@ homepage: https://github.com/Holmusk/postgresql-simple-named
bug-reports: https://github.com/Holmusk/postgresql-simple-named/issues
license: MPL-2.0
license-file: LICENSE
author: Holmusk
maintainer: Holmusk<[email protected]>
author: Dmitrii Kovanikov, Veronika Romashkina
maintainer: Holmusk <[email protected]>
copyright: 2019 Holmusk
category: Database
build-type: Simple
Expand Down
32 changes: 18 additions & 14 deletions src/PgNamed.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,19 @@

{- | Introduces named parameters for @postgresql-simple@ library.
It uses @?@ question mark symbol as the indicator of the named parameter which
is replaced with the standard syntax with question marks. Check out the example
of usage:
is replaced with the standard syntax with question marks.
Check out the example of usage:
@
queryNamed [sql|
'queryNamed' [sql|
SELECT *
FROM users
WHERE foo = ?foo
AND bar = ?bar
AND baz = ?foo
|] [ "foo" =? "fooBar"
, "bar" =? "barVar"
|] [ "foo" '=?' "fooBar"
, "bar" '=?' "barVar"
]
@
-}
Expand All @@ -28,6 +29,7 @@ module PgNamed

-- * Errors
, PgNamedError (..)
, WithNamedError

-- * Functions to deal with named parameters
, extractNames
Expand Down Expand Up @@ -71,15 +73,15 @@ data NamedParam = NamedParam
data PgNamedError
-- | Named parameter is not specified.
= PgNamedParam Name
-- | Query has no names inside but was called with named functions,
-- | Query has no names inside but was called with named functions.
| PgNoNames PG.Query
-- | Query contains an empty name.
| PgEmptyName PG.Query
deriving (Eq)


-- | Type alias for monads that can throw errors of the 'PgNamedError' type.
type WithError = MonadError PgNamedError
type WithNamedError = MonadError PgNamedError

instance Show PgNamedError where
show e = "PostgreSQL named parameter error: " ++ case e of
Expand All @@ -99,8 +101,8 @@ lookupName n = lookup n . map (\NamedParam{..} -> (namedParamName, namedParamPar
SELECT name, user FROM users WHERE id = ?id
@
and returns either the error or query with all all names replaced by
questiosn marks @?@ with list of the names in the order of their appearance.
and returns either the error or the query with all names replaced by
question marks @?@ with the list of the names in the order of their appearance.
For example:
Expand Down Expand Up @@ -132,9 +134,11 @@ extractNames qr = go (PG.fromQuery qr) >>= \case
isNameChar c = isAlphaNum c || c == '_'


-- | Returns the list of values to use in query by given list of 'Name's.
{- | Returns the list of values to use in query by given list of 'Name's.
Throws 'PgNamedError' if any named parameter is not specified.
-}
namesToRow
:: forall m . WithError m
:: forall m . WithNamedError m
=> NonEmpty Name -- ^ List of the names used in query
-> [NamedParam] -- ^ List of the named parameters
-> m (NonEmpty PG.Action)
Expand Down Expand Up @@ -176,7 +180,7 @@ queryNamed dbConnection [sql|
@
-}
queryNamed
:: (MonadIO m, WithError m, PG.FromRow res)
:: (MonadIO m, WithNamedError m, PG.FromRow res)
=> PG.Connection -- ^ Database connection
-> PG.Query -- ^ Query with named parameters inside
-> [NamedParam] -- ^ The list of named parameters to be used in the query
Expand All @@ -197,7 +201,7 @@ executeNamed dbConnection [sql|
@
-}
executeNamed
:: (MonadIO m, WithError m)
:: (MonadIO m, WithNamedError m)
=> PG.Connection -- ^ Database connection
-> PG.Query -- ^ Query with named parameters inside
-> [NamedParam] -- ^ The list of named parameters to be used in the query
Expand All @@ -208,7 +212,7 @@ executeNamed conn qNamed params =

-- | Helper to use named parameters.
withNamedArgs
:: WithError m
:: WithNamedError m
=> PG.Query
-> [NamedParam]
-> m (PG.Query, NonEmpty PG.Action)
Expand Down

0 comments on commit f590551

Please sign in to comment.