2016-12-24 12:34:27 +00:00
# purescript-postgresql-client
purescript-postgresql-client is a PostgreSQL client library for PureScript.
2016-12-25 22:58:29 +00:00
2018-04-22 14:47:07 +00:00
## Install
2018-04-21 11:12:20 +00:00
To use this library, you need to add `pg` and `decimal.js` as an npm dependency. You can also
2018-04-22 14:52:32 +00:00
find first of them on [https://github.com/brianc/node-postgres][pg].
2017-06-08 12:05:06 +00:00
2018-10-21 01:24:58 +00:00
## Usage
2018-10-21 01:58:45 +00:00
This guide is a literate Purescript file which is extracted into testing module (using [`literate-purescript` ](https://github.com/Thimoteus/literate-purescript )) so it is a little verbose.
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
Let's start with imports.
```purescript
2018-10-21 01:24:58 +00:00
module Test.Example where
import Prelude
2018-10-21 02:22:16 +00:00
import Database.PostgreSQL (defaultPoolConfiguration, command, execute, newPool, query, Query(Query), withConnection)
2018-10-21 01:24:58 +00:00
import Database.PostgreSQL.Row (Row0(Row0), Row3(Row3))
import Data.Decimal as Decimal
import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\))
import Effect.Aff (Aff)
2018-10-21 01:56:11 +00:00
import Effect.Class (liftEffect)
import Test.Assert (assert)
2018-10-21 09:39:25 +00:00
```
The whole API for interaction with postgres is performed asynchronously in `Aff` .
We assume here that postgres is running on a standard local port
with `ident` authentication so configuration can be nearly empty (`defaultPoolConfiguration`).
It requires only database name which we pass to `newPool` function.
We setup also `idleTimeoutMillis` value because this code
is run by our test suite and we want to exit after execution quickly ;-)
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
```purescript
2018-10-21 01:24:58 +00:00
run ∷ Aff Unit
run = do
pool < - newPool ( ( defaultPoolConfiguration " purspg " ) { idleTimeoutMillis = Just 1000 } )
withConnection pool \conn -> do
2018-10-21 09:39:25 +00:00
```
We can now create our temporary table which we are going to query in this example.
`execute` ignores result value which is what we want in this case.
```purescript
2018-10-21 01:24:58 +00:00
execute conn (Query """
2018-10-21 01:56:11 +00:00
CREATE TEMPORARY TABLE fruits (
2018-10-21 01:24:58 +00:00
name text NOT NULL,
delicious boolean NOT NULL,
price NUMERIC(4,2) NOT NULL,
added TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (name)
);
""") Row0
2018-10-21 09:39:25 +00:00
```
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
We can insert some data calling `execute` function with `INSERT` statement.
Please notice that we are passing a tuple of arguments to this query
using dedicated constructor. In this case `Row3` .
This library provides types from `Row0` to `Row19` and they are wrappers which
provides instances for automatic conversions from and to SQL values. For details
you can check classes like `ToSQLRow` , `ToSQLValue` , `FromSQLRow` and `FromSQLValue` .
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
```purescript
2018-10-21 01:24:58 +00:00
execute conn (Query """
2018-10-21 01:56:11 +00:00
INSERT INTO fruits (name, delicious, price)
2018-10-21 01:24:58 +00:00
VALUES ($1, $2, $3)
2018-10-21 01:56:11 +00:00
""") (Row3 "coconut" true (Decimal.fromString "8.30"))
2018-10-21 09:39:25 +00:00
```
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
We can also use nested tuples instead of `Row*` constructors. This can be a bit more
verbose but is not restricted to limited and constant number of arguments.
`/\` is just an alias for the `Tuple` constructor from `Data.Tuple.Nested` .
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
```purescript
2018-10-21 01:24:58 +00:00
execute conn (Query """
2018-10-21 01:56:11 +00:00
INSERT INTO fruits (name, delicious, price)
2018-10-21 01:24:58 +00:00
VALUES ($1, $2, $3)
2018-10-21 01:56:11 +00:00
""") ("lemon" /\ false /\ Decimal.fromString "3.30")
2018-10-21 09:39:25 +00:00
```
Of course `Row*` types and nested tuples can be also used when we are fetching
data from db.
`query` function processes db response and returns an `Array` of rows.
2018-10-21 01:56:11 +00:00
2018-10-21 09:39:25 +00:00
```purescript
2018-10-21 01:56:11 +00:00
names < - query conn ( Query " " "
SELECT name, delicious
FROM fruits
ORDER BY name ASC
""") Row0
liftEffect << < assert $ names = = [" coconut " / \ true , " lemon " / \ false ]
2018-10-21 09:39:25 +00:00
```
There is also a `command` function at our disposal.
Some postgres SQL expressions return a "command tag" which carries
a value of rows which were affected by a given query.
For example we can have: `DELETE rows` , `UPDATE rows` , `INSERT oid rows` etc.
This function should return `rows` value associated with given response.
2018-10-21 01:24:58 +00:00
2018-10-21 09:39:25 +00:00
```purescript
2018-10-21 02:22:16 +00:00
deleted < - command conn ( Query " " " DELETE FROM fruits " " " ) Row0
liftEffect < < < assert $ deleted = = 2
2018-10-21 01:24:58 +00:00
```
2018-10-21 01:32:06 +00:00
## Testing
Currently tests are prepared to work with default and local setup for postgresql (ident authentication, standart port etc.).
If you think that we should add configuration layer for our test runner please open an issue.
2018-10-21 02:22:16 +00:00
To run suite please:
2018-10-21 01:32:06 +00:00
* prepare empty "purspg" database
* `$ nmp install literate-purescript`
* `$ ./bin/test.sh`
2018-10-21 01:24:58 +00:00
2018-04-22 14:52:32 +00:00
## Generating SQL Queries
2018-04-22 14:47:07 +00:00
2017-06-03 12:06:09 +00:00
The purspgpp preprocessor has been replaced by [sqltopurs], which is a code
generator instead of a preprocessor, and easier to use.
[sqltopurs]: https://github.com/rightfold/sqltopurs
2018-04-22 14:47:07 +00:00
2018-10-21 01:24:58 +00:00