pgde 0.3.0

A macro library for consuming PostgreSQL row data into structs.
Documentation
A simple library for consuming `tokio_postgres::row::Row` data into structs that derive the `RowConsumer` trait.

This crate provides a variety of derivable implementations that can be used to consume PostgreSQL data depending on preference.
- `from_row`
- `from_rows`
- `consume`
- `consume_json` if Feature `consume_json` is enabled

The latter implementations are built off of `from_row`.

Most of the complex PostgreSQL types are not supported, namely arrays. Consequently `Vec` types on structs are not currently supported.

## Features


| Feature | Description | Extra dependencies | Default |
| ------- | ----------- | ------------------ | ------- |
| `consume_json` | Implements `consume_json` on classes that derive the `RowConsumer` trait | serde, serde_json | No |
| `geo` | Implements crate on `geo_types::Point<f64>`, `geo_types::Rect<f64>`, and `geo_types::LineString<f64>` | geo-types | No |
| `mac` | Implements crate on `eui48::MacAddress` | eui48 | No |
| `json` | Implements crate on `serde_json::Value` | serde_json | No |
| `uuid` | Implements crate on `uuid::Uuid` | uuid | No |

## Examples

### `consume`

You may use `consume` to consume PostgreSQL row data into a struct like so.
```
# tokio_test::block_on(async {

use pgde::ConsumeError;
use pgde::RowConsumer;
use pgde_derive::RowConsumer;
use tokio_postgres::{NoTls, Row};

#[derive(RowConsumer)]

struct Foo {
    Id: i32,
    Data: String,
}

match tokio_postgres::connect("host=localhost user=postgres password=password dbname=postgres", NoTls).await {
    Ok(v) => {
        let client = v.0;
        let conn = v.1;

        tokio::spawn(async move {
            if let Err(e) = conn.await {
                eprintln!("connection error: {}", e);
            }
        });

        let query = "select * from public.\"Foo\";";

        match Foo::consume(&client, query, &[]).await {
            Ok(v) => { // v is of type Vec<Foo>
                match v.first() {
                    Some(v) => println!("Id {} has Data {}", v.Id, v.Data),
                    None => eprintln!("No data in table"),
                }
            },
            Err(v) => match v {
                ConsumeError::ConversionError => eprintln!("Could not convert data"),
                ConsumeError::DatabaseConnectionError => eprintln!("Database errored on processing the query"),
            },
        };
    },
    Err(_) => eprintln!("Could not connect to database"),
};

# })

```

This crate also implements `consume` on the following data types.

| Type | Feature |
| ---- | ------- |
| `bool` | `default` |
| `i8` | `default` |
| `i16` | `default` |
| `i32` | `default` |
| `u32` | `default` |
| `i64` | `default` |
| `f32` | `default` |
| `f64` | `default` |
| `Vec<u8>` | `default` |
| `String` | `default` |
| `SystemTime` | `default` |
| `IpAddr` | `default` |
| `geo_types::Point<f64>` | `geo` |
| `geo_types::Rect<f64>` | `geo` |
| `geo_types::LineString<f64>` | `geo` |
| `eui48::MacAddress` | `mac` |
| `serde_json::Value` | `json` |
| `uuid::Uuid` | `uuid` |

Which can be used by doing something like the following.

```
# tokio_test::block_on(async {

use pgde::ConsumeError;
use pgde::RowConsumer;
use tokio_postgres::{NoTls, Row};

match tokio_postgres::connect("host=localhost user=postgres password=password dbname=postgres", NoTls).await {
    Ok(v) => {
        let client = v.0;
        let conn = v.1;

        tokio::spawn(async move {
            if let Err(e) = conn.await {
                eprintln!("connection error: {}", e);
            }
        });

        let query = "select 1;";

        match i32::consume(&client, query, &[]).await {
            Ok(v) => { // v is of type Vec<i32>
                match v.first() {
                    Some(v) => println!("1 is {}", *v),
                    None => eprintln!("No data received"),
                }
            },
            Err(v) => match v {
                ConsumeError::ConversionError => eprintln!("Could not convert data"),
                ConsumeError::DatabaseConnectionError => eprintln!("Database errored on processing the query"),
            },
        };
    },
    Err(_) => eprintln!("Could not connect to database"),
};

# })

```

## Other implementations

The other implementations in this crate, `from_row` and `from_rows`, can be used if their use better matches your preference. Refer to the construction of `from_rows` and `consume` for examples on their uses, respectively.

### Features

The following features provide implementations on the corresponding types.

| Feature | Rust Type |
| ------- | --------- |
| `geo` | `geo_types::Point<f64>`, `geo_types::Rect<f64>`, `geo_types::LineString<f64>` |
| `json` | `serde_json::Value` |
| `mac` | `eui48::MacAddress` |
| `uuid` | `uuid::Uuid` |

With the `consume_json` feature you get access to `consume_json`, which returns json data in a `String`.
```
# tokio_test::block_on(async {

use pgde::ConsumeError;
use pgde::RowConsumer;
use pgde_derive::RowConsumer;
use serde::Serialize;
use tokio_postgres::{NoTls, Row};

#[derive(Serialize, RowConsumer)]

struct Foo {
    Id: i32,
    Data: String,
}

match tokio_postgres::connect("host=localhost user=postgres password=password dbname=postgres", NoTls).await {
    Ok(v) => {
        let client = v.0;
        let conn = v.1;

        tokio::spawn(async move {
            if let Err(e) = conn.await {
                eprintln!("connection error: {}", e);
            }
        });

        let query = "select * from public.\"Foo\";";

        match Foo::consume_json(&client, query, &[]).await {
            Ok(v) => { // v is of type String
                println!("Received json data...\n{}", v);
            },
            Err(v) => eprintln!("An error occurred while querying database"),
        };
    },
    Err(_) => eprintln!("Could not connect to database"),
};

# })

```

## Testing

Testing requires access to a PostgreSQL database with no tables. Setting the following environment variables will allow you to test.

| Environment Variable | Description |
| -------------------- | ----------- |
| `PGDE_DB_HOST` | The host that the database can be accessed at. |
| `POSTGRES_USER` | The user credential to provide. |
| `POSTGRES_PASSWORD` | The password to provide. |
| `POSTGRES_DB` | The name of the database to use for testing. |