3

Here is the code I use to insert data in a Postgres database using the postgres crate (not present on Rust Playground unfortunately):

With the following Cargo.toml:

[package]
name = "suff-import"
version = "0.1.0"
authors = ["greg"]

[dependencies]
csv = "1"
postgres = "0.15"
uuid = "0.7"

File main.rs:

extern crate csv;
extern crate postgres;
extern crate uuid;

use uuid::Uuid;
use postgres::{Connection, TlsMode};
use std::error::Error;
use std::io;
use csv::StringRecord;

struct Stuff {
    stuff_id: Uuid,
    created_at: String,
    description: String,
    is_something: bool,
}

impl Stuff {
    fn from_string_record(record: StringRecord) -> Stuff {
        Stuff {
            stuff_id: Uuid::parse_str(record.get(0).unwrap()).unwrap(),
            created_at: record.get(1).unwrap().to_string(),
            description: record.get(2).unwrap().to_string(),
            is_something: record.get(3).unwrap().to_string().parse::<i32>().unwrap() == 2,
        }
    }
}

fn save_row(dbcon: &Connection, stuff: Stuff) -> Result<(), Box<Error>> {
    dbcon.execute(
        "insert into public.stuff (stuff_id, created_at, description, is_something) values ($1::uuid, $2, $3, $4)",
        &[&format!("{}", &stuff.stuff_id).as_str(), &stuff.created_at, &stuff.description, &stuff.is_something]
    )?;
    Ok(())
}


fn import() -> Result<(), Box<Error>> {
    let mut reader = csv::Reader::from_reader(io::stdin());
    let dbcon = Connection::connect("postgres://[email protected]/gregoire", TlsMode::None).unwrap();

    for result in reader.records() {
        let record = result?;
        println!(".");
        save_row(&dbcon, Stuff::from_string_record(record))?;
    }

    Ok(())
}

fn main() {
    if let Err(error) = import() {
        println!("There were some errors: {}", error);
        std::process::exit(1);
    }
}

The program compiles, but it exits when run with the error message:

./target/debug/suff-import <<EOF
stuff_id,created_at,description,is_something
5252fff5-d04f-4e0f-8d3e-27da489cf40c,"2019-03-15 16:39:32","This is a description",1
EOF
.
There were some errors: type conversion error: cannot convert to or from a Postgres value of type `uuid`

I tested turning the UUID into a &str with the format! macro as Postgres should implicitly do the conversion to UUID, but it did not work (same error message). I then added an explicit $1::uuid in the Postgres query but the problem still occurs.

2
  • I'd say, either use $1::uuid and &stuff.stuff_id (no conversion to &str) or use $1 (no ::uuid) and &format!("{}", &stuff.stuff_id).as_str(). As is you're telling postgres to expect a UUID object, but you're passing a string… Commented Mar 18, 2019 at 13:52
  • @Jmb, the $1::uuid is a cast operator on the first argument, if the first argument is a string, it will be cast into a uuid. On the rust part, the array used to pass query parameters is an array of &str. I will follow @shepmaster instruction to provide a better question. Commented Mar 18, 2019 at 16:18

1 Answer 1

3

The crate page states:

Optional features

UUID type

UUID support is provided optionally by the with-uuid feature, which adds ToSql and FromSql implementations for uuid's Uuid type. Requires uuid version 0.5.

You haven't specified the feature, and you are using an incompatible version of uuid.

Cargo.toml

[package]
name = "repro"
version = "0.1.0"
edition = "2018"

[dependencies]
postgres = { version = "0.15.2", features = ["with-uuid"] }
uuid = "0.5"

Database setup

CREATE TABLE junk (id uuid);

Code

use postgres::{Connection, TlsMode};
use std::error::Error;
use uuid::Uuid;

fn main() -> Result<(), Box<Error>> {
    let conn = Connection::connect(
        "postgresql://shep@localhost:5432/stackoverflow",
        TlsMode::None,
    )
    .unwrap();

    let stuff_id = Uuid::default();

    conn.execute(
        "insert into public.junk (id) values ($1)",
        &[&stuff_id],
    )?;

    Ok(())
}

See also:

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.