how to using rust diesel to do the full text query - postgresql

I am trying to using diesel diesel = { version = "1.4.8", features = ["postgres","64-column-tables","chrono","serde_json"] } to do a full text query, this is the sql command look like:
SELECT * FROM article a WHERE to_tsvector('english', title) ## to_tsquery('english','Rate|Limiting')
how to using rust diesel to do this query? I am using the like right now and want to switch to full text search, this is the like query code main.rs look like:
#[macro_use]
extern crate diesel;
use diesel::{TextExpressionMethods, QueryDsl, RunQueryDsl};
use rust_wheel::config::db::config;
use crate::model::diesel::dict::dict_models::Article;
mod model;
fn main() {
use model::diesel::dict::dict_schema::article as article_table;
let connection = config::establish_connection();
let mut query = article_table::table.into_boxed::<diesel::pg::Pg>();
query = query.filter(article_table::title.like(format!("{}{}{}","%","demo","%")));
let query_result = query.load::<Article>(&connection);
}
and this is the schema files dict_schema.rs look like:
table! {
article (id) {
id -> Int8,
user_id -> Int8,
title -> Varchar,
author -> Varchar,
guid -> Varchar,
created_time -> Int8,
updated_time -> Int8,
link -> Nullable<Varchar>,
sub_source_id -> Int8,
cover_image -> Nullable<Varchar>,
channel_reputation -> Int4,
editor_pick -> Nullable<Int4>,
}
}
and this is the model files dict_models.rs look like:
// Generated by diesel_ext
#![allow(unused)]
#![allow(clippy::all)]
use std::io::Write;
use diesel::deserialize::FromSql;
use diesel::pg::Pg;
use diesel::serialize::{Output, ToSql};
use diesel::sql_types::Jsonb;
use rocket::serde::Serialize;
use serde::Deserialize;
use chrono::DateTime;
use chrono::Utc;
use crate::model::diesel::dict::dict_schema::*;
#[derive(Queryable,QueryableByName,Debug,Serialize,Deserialize,Default,Clone)]
#[table_name = "article"]
pub struct Article {
pub id: i64,
pub user_id: i64,
pub title: String,
pub author: String,
pub guid: String,
pub created_time: i64,
pub updated_time: i64,
pub link: Option<String>,
pub sub_source_id: i64,
pub cover_image: Option<String>,
pub channel_reputation: i32,
pub editor_pick: Option<i32>,
}
and this is the dependencies Cargo.toml look like:
[package]
name = "rust-learn"
version = "0.1.0"
edition = "2018"
[dependencies]
rocket = { version = "=0.5.0-rc.2", features = ["json"] }
serde = { version = "1.0.64", features = ["derive"] }
serde_json = "1.0.64"
serde_derive = "1.0"
# database
diesel = { version = "1.4.7", features = ["postgres","serde_json"] }
dotenv = "0.15.0"
jsonwebtoken = "7"
chrono = "0.4"
config = "0.11"
ring = "0.16.20"
md5 = "0.7.0"
data-encoding = "2.3.2"
diesel_full_text_search = "1.0.1"
bigdecimal = "0.3.0"
# reddwarf public component
rust_wheel = { git = "https://github.com/jiangxiaoqiang/rust_wheel.git" }
What shuld I do to change to like query to full text search query? I am searching from internet but no one talk about this issue. BTW: this is the cargo version:
➜ rust-learn git:(group-by) ✗ cargo version
cargo 1.62.0 (a748cf5a3 2022-06-08)
and this is the rust version:
➜ rust-learn git:(group-by) ✗ rustc --version
rustc 1.62.0 (a8314ef7d 2022-06-27)
any idea about this issue? what should i do to using the full text search in diesel?
I have tried to add the dependencies diesel_full_text_search = "1.0.1" and tweak the main.rs code like this:
#[macro_use]
extern crate diesel;
use diesel::{TextExpressionMethods, QueryDsl, RunQueryDsl};
use diesel_full_text_search::{to_tsquery, to_tsvector, TsQueryExtensions};
use rust_wheel::config::db::config;
use diesel_full_text_search::TsVectorExtensions;
use crate::model::diesel::dict::dict_models::Article;
mod model;
fn main() {
use model::diesel::dict::dict_schema::article as article_table;
let connection = config::establish_connection();
let mut query = article_table::table.into_boxed::<diesel::pg::Pg>();
let filter_title = "经济 文化";
let query_items: Vec<&str> = filter_title.trim().split_whitespace().collect();
let query_array = query_items.join(" & ");
let tsquery = to_tsquery(query_array);
let tsvector = to_tsvector("'dolphinzhcfg', title");
query = query.filter(&tsvector.matches(&tsquery));
let query_result = query.load::<Article>(&connection);
}
shows error:
mismatched types [E0308] expected `char`, found `&to_tsquery<String>`
what should I do to fixed this problem?

Checkout the following functions:
diesel_full_text_search::to_tsvector
diesel_full_text_search::to_tsquery
diesel_full_text_search::TsVectorExtensions::matches

Related

the trait `LoadConnection` is not implemented for `&diesel::PgConnection`

I want to create a rest api with rust and can't make it work.
My relevant code so far:
In the main.rs:
#[actix_web::main]
async fn main() -> std::io::Result<()> {
// Loading .env into environment variable.
dotenv::dotenv().ok();
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
// set up database connection pool
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL");
let manager = ConnectionManager::<PgConnection>::new(database_url);
let pool: DbPool = r2d2::Pool::builder()
.test_on_check_out(true)
.build(manager)
.expect("Could not build connection pool");
let port = std::env::var("PORT").expect("$PORT is not set.");
HttpServer::new(move || {
App::new()
.app_data(web::Data::new(pool.clone()))
.wrap(middleware::Logger::default())
.route("/", web::get().to(|| async { "Actix REST API" }))
.service(handlers::common::houses::index)
})
.bind(("0.0.0.0", port.parse().unwrap()))?
.run()
.await
}
The schema:
diesel::table! {
houses (id) {
id -> Int4,
user_id -> Varchar,
street -> Varchar,
figure -> Varchar,
floor -> Varchar,
create_date -> Timestamp,
update_date -> Timestamp,
is_deleted -> Bool,
}
}
The model:
#[derive(Debug, Serialize, Deserialize, Queryable)]
pub struct House {
pub id: i32,
pub user_id: String,
pub street: String,
pub figure: String,
pub floor: String,
pub create_date: chrono::NaiveDateTime,
pub update_date: chrono::NaiveDateTime,
pub is_deleted: bool,
}
The handler:
#[get("/houses")]
async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
let houses = web::block(move || {
let conn = &pool.get()?;
find_all(&conn)
})
.await?
.map_err(actix_web::error::ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(houses))
}
fn find_all(conn: &PgConnection) -> Result<Vec<House>, DbError> {
use crate::schemas::common::houses::houses::dsl::*;
let items =houses.load::<House>(&mut conn)?;
Ok(items)
}
The dependencies are:
[dependencies]
actix-web = "4"
chrono = { version = "0.4.19", features = ["serde"] }
diesel = { version = "2.0.3", features = ["postgres", "r2d2", "chrono"] }
dotenv = "0.15.0"
env_logger = "0.10.0"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0"`
It keeps giving an error, and I don't understand why.
The error is:
`error[E0277]: the trait bound `&diesel::PgConnection: LoadConnection` is not satisfied src\handlers\common\houses.rs:25:37
| 25 | let items =houses.load::<House>(&mut conn)?;
| ---- -^^^^^^^^
| | | the trait `LoadConnection` is not implemented for `&diesel::PgConnection` help: consider removing the leading `&`-reference required by a bound introduced by this call
| note: required for `table` to implement `LoadQuery<'_, &diesel::PgConnection, House>` note: required by a bound in `diesel::RunQueryDsl::load`
I've seen a similar error with the diesel version 1.4, but I think that this version is different.
Plus I'm starting with rust and I'm a little lost in general at the moment.
I was hopping someone knows what the problem is and how to fix it.
PgConnection implements LoadConnection but &PgConnection does not (note the extra &).
Make conn mutable and pass as a mutable reference:
#[get("/houses")]
async fn index(pool: web::Data<DbPool>) -> Result<HttpResponse, Error> {
let houses = web::block(move || {
let mut conn = pool.get()?; // <------------
find_all(&mut conn) // <------------
})
.await?
.map_err(actix_web::error::ErrorInternalServerError)?;
Ok(HttpResponse::Ok().json(houses))
}
fn find_all(conn: &mut PgConnection) -> Result<Vec<House>, DbError> {
// ^^^ <------------
use crate::schemas::common::houses::houses::dsl::*;
let items = houses.load::<House>(conn)?; // <------------
Ok(items)
}

Problems working with rust and postgres data types

I'm triying to do an Api REST with rust and postres but I cant make it work because the relation between these two.
The actual problem is that I have a column in postgres as jsonb and when I return the data and try to save it in a struct always gives error. Same problem when I try to save the data.
This are the models.(The option is only because I'm testing thing, it should return a value)
#[derive(Debug, Serialize, Deserialize)]
pub struct CategoryView {
pub id: i32,
pub category_name: String,
pub category_custom_fields: Option<serde_json::Value>,
}
#[derive(Debug, Serialize, Deserialize)]
pub struct CategoryPayload {
pub category_name: String,
pub category_custom_fields: Option<serde_json::Value>,
}
This are the postgres queries:
fn find_all(conn: &mut DbPooled) -> Result<Vec<CategoryView>, DbError> {
let mut query = "SELECT id, category_name, category_custom_fields FROM accounting.categories".to_owned();
query.push_str(" WHERE user_id = $1");
query.push_str(" AND is_deleted = false");
let items = conn.query(&query, &[&unsafe { CURRENT_USER.to_owned() }])?;
let items_view: Vec<CategoryView> = items
.iter()
.map(|h| CategoryView {
id: h.get("id"),
category_name: h.get("category_name"),
category_custom_fields: h.get("category_custom_fields"),
})
.collect();
Ok(items_view)
}
fn add(payload: &CategoryPayload, conn: &mut DbPooled) -> Result<CategoryView, DbError> {
let mut query =
"INSERT INTO accounting.categories (user_id, category_name, category_custom_fields, create_date, update_date)"
.to_owned();
query.push_str(" VALUES ($1, $2, $3, now(), now())");
query.push_str(" RETURNING id");
let item_id = conn
.query_one(
&query,
&[
&unsafe { CURRENT_USER.to_owned() },
&payload.category_name,
&payload.category_custom_fields,
],
)?
.get(0);
let inserted_item = CategoryView {
id: item_id,
category_name: payload.category_name.to_string(),
category_custom_fields: payload.category_custom_fields,
};
Ok(inserted_item)
}
with update happens to but I think is the same solution that the one form the add function.
The error is:
the trait bound `serde_json::Value: ToSql` is not satisfied
the following other types implement trait `ToSql`:
&'a T
&'a [T]
&'a [u8]
&'a str
Box<[T]>
Box<str>
Cow<'a, str>
HashMap<std::string::String, std::option::Option<std::string::String>, H>
and 17 others
required for `std::option::Option<serde_json::Value>` to implement `ToSql`
required for the cast from `std::option::Option<serde_json::Value>` to the object type `dyn ToSql + Sync`rustcClick for full compiler diagnostic`
For what I read serde_json::Value is the equivalent to jsonb so I don't understand it.
I had a similar problem previously trying to work with a decimal value in postgres, I had to change it to integer and save the value multiplied in the database. Is a money column so maybe if you help me with that too I will change it back.
I was hopping some could explain to me how to fix it and why this happens so I can avoid have to ask for help with the datatypes in the future.
The problem was in the depencies.
It looks like some dependencies have features that add aditional functionablility.
I had installed the dependencie without any feature so when I added the features it started to work without issues.
Only had to change from:
[dependencies]
postgres = "0.19.4"
to:
[dependencies]
postgres = { version = "0.19.4", features = ["with-chrono-0_4", "with-serde_json-1"] }
Chrono for dates and serde_json for jsonb.
I'll check the decimal problem but I think will be the same solution.

DateTime<Utc> compiles but not DateTime<Local> querying a table with a column defined as timestamp with time zone

I have a postgresql-table with a column defined as timestamp with time zone. The table is mapped to this struct:
#[derive(Serialize, Queryable)]
pub struct Location {
pub publication_time: DateTime<Utc>,
pub id: i32,
pub name: String,
pub latitude: BigDecimal,
pub longitude: BigDecimal,
}
The schema have this definition:
table! {
locations {
publication_time -> Timestamptz,
id -> Integer,
name -> Text,
latitude -> Numeric,
longitude -> Numeric,
}
}
(partial) Cargo.toml:
serde = "1.0.125"
serde_json = "1.0.64"
serde_derive = "1.0.125"
diesel = { version = "1.4.6", features = ["postgres", "r2d2", "chrono", "numeric"] }
bigdecimal = { version = "0.1.0", features = ["serde"] }
chrono = { version = "0.4.19", features = ["serde"] }
The function that queries the database:
fn get_all_locations(pool: web::Data<Pool>) -> Result<Vec<Location>, diesel::result::Error> {
let conn = pool.get().unwrap();
let items = locations.load::<Location>(&conn)?;
Ok(items)
}
This is then serialized to a JSON-array using serde_json. The DateTime in the database is 2021-04-08 15:02:02.514+02. When DateTime is Utc the program compiles fine, but the DateTime shown in UTC like 2021-04-08T13:02:02.514Z. I changed publication_time to DateTime<Local> to retain the time zone information but then cargo build fails with:
error[E0277]: the trait bound `DateTime<Local>: FromSql<diesel::sql_types::Timestamptz, Pg>` is not satisfied
--> src/controller.rs:21:27
|
21 | let items = locations.load::<Location>(&conn)?;
| ^^^^ the trait `FromSql<diesel::sql_types::Timestamptz, Pg>` is not implemented for `DateTime<Local>`
|
= help: the following implementations were found:
<DateTime<Utc> as FromSql<diesel::sql_types::Timestamptz, Pg>>
= note: required because of the requirements on the impl of `diesel::Queryable<diesel::sql_types::Timestamptz, Pg>` for `DateTime<Local>`
= note: 2 redundant requirements hidden
= note: required because of the requirements on the impl of `diesel::Queryable<(diesel::sql_types::Timestamptz, diesel::sql_types::Integer, diesel::sql_types::Text, diesel::sql_types::Numeric, diesel::sql_types::Numeric), Pg>` for `models::Location`
= note: required because of the requirements on the impl of `LoadQuery<_, models::Location>` for `locations::table`
I have another program that insert to this table and this works and the only difference is derive(Deserialize, Insertable).
#[derive(Deserialize, Insertable)]
pub struct Location {
pub publication_time: DateTime<Local>,
pub id: i32,
pub name: String,
pub latitude: BigDecimal,
pub longitude: BigDecimal,
}
Mapping a Timestamptz field to a DateTime<Local> is not supported by diesel itself, as it only provides the corresponding impl for DateTime<Utc>.
You can work this around by using the #[diesel(deserialize_as = "…")] attribute on the corresponding field and providing your own deserialization wrapper:
#[derive(Serialize, Queryable)]
pub struct Location {
#[diesel(deserialize_as = "MyDateTimeWrapper")]
pub publication_time: DateTime<Local>,
pub id: i32,
pub name: String,
pub latitude: BigDecimal,
pub longitude: BigDecimal,
}
pub struct MyDatetimeWrapper(DateTime<Local>);
impl Into<DateTime<Local>> for MyDatetimeWrapper {
fn into(self) -> DateTime<Local> {
self.0
}
}
impl<DB, ST> Queryable<ST, DB> for MyDateTimeWrapper
where
DB: Backend,
DateTime<Utc>: Queryable<ST, DB>,
{
type Row = <DateTime<Utc> as Queryable<ST, DB>>::Row;
fn build(row: Self::Row) -> Self {
Self(<DateTime<Utc> as Queryable<ST, DB>>::build(row).with_timezone(&Local))
}
}

How to insert HashMap into PostgreSQL as JSON type?

contacts has a data structure as HashMap, I'm using PostgreSQL client -rust-postgres to insert contact's key and value into a table, then I want to select from the table. Below is what I tried so far. I need help with writing the right syntax.
use postgres::{Client, NoTls};
use std::collections::HashMap;
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Client::connect("host=127.0.0.1 user=postgres", NoTls)?;
client.simple_query("
DROP TABLE
IF EXISTS following_relation;
")?;
client.simple_query("
CREATE TABLE following_relation (
id SERIAL NOT NULL PRIMARY KEY,
relation JSON NOT NULL
)
")?;
let mut contacts = HashMap::new();
let mut v: Vec<String> = Vec::new();
v = vec!["jump".to_owned(), "jog".to_string()];
contacts.insert("Ashley", v.clone());
for (name, hobby) in contacts.iter() {
// 1. How to write sql statement with parameters?
client.execute(
"INSERT INTO following_relation(relation)
VALUE ('{"name" : $1, "hobby" : $2}')",
&[&name, &hobby],
)?;
}
for row in client.query("SELECT id, relation FROM following_relation", &[])? {
// 2. How to read from parse the result?
let id: i32 = row.get(0);
let relation = row.get(1);
//println!("found person: {} {} {:?}", id, relation["name"], relation["hobby"]);
}
Ok(())
}
I've been given the hints
Like the error message says, your query has VALUE but it needs to be VALUES.
Query parameters cannot be interpolated into strings. You should build the object in Rust, and use https://docs.rs/postgres/0.17.0/postgres/types/struct.Json.html to wrap the types when inserting.
I have no idea how to apply pub struct Json<T>(pub T); here.
How to build the query required in function execute?
pub fn execute<T: ?Sized>(
&mut self,
query: &T,
params: &[&(dyn ToSql + Sync)]
) -> Result<u64, Error>
where
T: ToStatement,
UPDATED, I tried with a more brief code sample
use postgres::{Client, NoTls};
use postgres::types::Json;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
struct relations {
name : String,
hobby: Vec<String>
}
pub struct Json<T>(pub T);
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Client::connect("host=127.0.0.1 user=postgres", NoTls)?;
client.simple_query("
DROP TABLE
IF EXISTS following_relation;
")?;
client.simple_query("
CREATE TABLE following_relation (
id SERIAL PRIMARY KEY,
relation JSON NOT NULL
)
")?;
let rel = relations {
name: "czfzdxx".to_string(),
hobby: vec![
"basketball".to_string(),
"jogging".to_string()
],
};
client.execute(
r#"INSERT INTO following_relation(relation)
VALUE ($1)"#,
&[&Json(&rel)]
)?;
Ok(())
}
I get
error[E0432]: unresolved import `postgres::types::Json`
You want Rust raw string literal:
for (name, hobby) in contacts.iter() {
client.execute(
r#"INSERT INTO following_relation(relation)
VALUE ('{"name" : ($1), "hobby" : ($2)}')"#,
&[&name, &following],
)?;
}
Between the start r#" and the end "#, your string literals can have any character except # itself without escaping. If you also want # itself, then starts the raw string literals with multiple #s and ends with matching number of #s.
Here is main.rs:
use postgres::{Client, NoTls};
use serde::{Deserialize, Serialize};
use postgres_types::Json;
use postgres_types::{FromSql};
#[derive(Debug, Deserialize, Serialize, FromSql)]
struct Relation {
name : String,
hobby: Vec<String>
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let mut client = Client::connect("host=127.0.0.1 user=postgres", NoTls)?;
client.simple_query("
DROP TABLE
IF EXISTS following_relation;
")?;
client.simple_query("
CREATE TABLE following_relation (
id SERIAL PRIMARY KEY,
relation JSON NOT NULL
)
")?;
let rel = Relation {
name: "czfzdxx".to_string(),
hobby: vec![
"basketball".to_string(),
"jogging".to_string()
],
};
client.execute(
"INSERT INTO following_relation (relation) VALUES ($1)",
&[&Json::<Relation>(rel)]
)?;
for row in &client.query("SELECT relation FROM following_relation", &[]).unwrap() {
let rel: Json<Relation> = row.get(0);
println!("{:?}", rel);
}
Ok(())
}
and Cargo.toml:
[package]
name = "testapp"
version = "0.1.0"
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
postgres = {version = "0.17.0"}
tokio-postgres = "0.5.1"
serde = {version = "1.0.104", features = ["derive"]}
postgres-types = {version = "0.1.0", features = ["derive", "with-serde_json-1"]}
serde_json = "1.0.45"
And here is the relevant documentation used: postgres_types and postgres. Search for serde_json, ToSql and FromSql traits are implemented for this third-party type.

How can I read a timestamp with timezone (timestamptz) value from PostgreSQL in Rust?

What's the right Rust data type to use for a timestamptz when using postgres version 0.17.0 with Rust 1.40.0?
I read the docs for Timestamp but have no idea what this means or how to implement it.
The readme for 0.17.0-alpha.1 has a table which says that timezone corresponds to Rust types time::Timespec or chrono::DateTime<Utc> but neither works for me.
When I try to use the stipulated features in my Cargo.toml using:
[dependencies]
postgres = {version="0.17.0-alpha.1", features=["with-chrono", "with-time"]}
I get this error:
the package `mypackage` depends on `postgres`, with features: `with-time, with-chrono` but `postgres` does not have these features.
Here's some functional code and corresponding dependencies. I want to be able to read and print the timezone per row (commented out)
main.rs
use postgres::{Client, Error, NoTls};
extern crate chrono;
use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
extern crate time;
use time::Timespec;
pub fn main() -> Result<(), Error> {
let mut client = Client::connect("host=localhost user=postgres", NoTls)?;
client.simple_query(
"
CREATE TABLE mytable (
name text NOT NULL,
timestamp timestamptz NOT NULL)",
)?;
client.execute("INSERT INTO mytable VALUES ('bob', now());", &[])?;
for row in client.query("SELECT * FROM mytable", &[])? {
let name: &str = row.get(0);
// let timestamp: chrono::DateTime<Utc> = row.get(1); //doesnt work
// let timestamp: Timespec = row.get(1); //doesnt work
println!("name: {}", name);
// println!("timestamp: {}", timestamp);
}
Ok(())
}
Uncommenting
let timestamp: Timespec = row.get(1); //doesnt work
error[E0277]: the trait bound `time::Timespec: postgres_types::FromSql<'_>` is not satisfied
--> src/main.rs:30:39 | 30 |
let timestamp: Timespec = row.get(1); //doesnt work
^^^ the trait `postgres_types::FromSql<'_>` is not implemented for `time::Timespec`
Uncommenting
let timestamp: chrono::DateTime<Utc> = row.get(1); //doesnt work
error[E0277]: the trait bound `chrono::DateTime<chrono::Utc>: postgres_types::FromSql<'_>` is not satisfied
--> src/main.rs:29:52 29 |
let timestamp: chrono::DateTime<Utc> = row.get(1); //doesnt work
^^^ the trait `postgres_types::FromSql<'_>` is not implemented for `chrono::DateTime<chrono::Utc>`
Cargo.toml
[dependencies]
postgres = "0.17.0"
chrono = "0.4.10"
time = "0.1.14"
This link says to use time = "0.1.14". latest version also fails https://crates.io/crates/postgres/0.17.0-alpha.1
Once you know what features are available, it's reasonably direct to see that you need to use the with-chrono-0_4 feature.
use chrono::{DateTime, Utc}; // 0.4.10
use postgres::{Client, Error, NoTls}; // 0.17.0, features = ["with-chrono-0_4"]
pub fn main() -> Result<(), Error> {
let mut client = Client::connect("host=localhost user=stack-overflow", NoTls)?;
client.simple_query(
r#"
CREATE TABLE mytable (
name text NOT NULL,
timestamp timestamptz NOT NULL
)"#,
)?;
client.execute("INSERT INTO mytable VALUES ('bob', now());", &[])?;
for row in client.query("SELECT * FROM mytable", &[])? {
let name: &str = row.get(0);
let timestamp: DateTime<Utc> = row.get(1);
dbg!(name, timestamp);
}
Ok(())
}
[src/main.rs:20] name = "bob"
[src/main.rs:20] timestamp = 2020-01-16T01:21:58.755804Z
Thanks to https://github.com/sfackler/rust-postgres/issues/211, this works using version 0.15.0 of the postgres crate, but I'd like a solution using version 0.17.0.
main.rs
extern crate postgres;
use postgres::{Connection, TlsMode};
extern crate chrono;
use chrono::{DateTime, Local, NaiveDateTime, TimeZone, Utc};
fn main() {
let conn = Connection::connect("postgresql://postgres#localhost:5432", TlsMode::None).unwrap();
conn.execute(
"CREATE TABLE person (
name VARCHAR NOT NULL,
timestamp timestamptz
)",
&[],).unwrap();
conn.execute("INSERT INTO person VALUES ('bob', now());", &[]).unwrap();
for row in &conn.query("SELECT * FROM person", &[]).unwrap() {
let name: String = row.get(0);
let timestamp: chrono::DateTime<Utc> = row.get(1);
println!("name: {}", name);
println!("timestamp: {}", timestamp);
}
}
Output:
name: bob
timestamp: 2020-01-15 23:56:05.411304 UTC
Cargo.toml
[dependencies]
postgres = { version = "0.15", features = ["with-chrono"] }
chrono = "0.4.10"
time = "0.1.14"