在 Rust 中向 postgres 摄取时间戳时如何避免字符串转换?
How can I avoid string conversions when ingesting timestamps to postgres in Rust?
我正在使用 rust-postgres 箱来摄取数据。这是一个成功添加行的工作示例:
let name: &str = "hello from rust";
let val: i32 = 123;
let now: DateTime<Utc> = Utc::now();
let timestamp = now.format("%Y-%m-%dT%H:%M:%S%.6f").to_string();
client.execute(
"INSERT INTO trades VALUES(to_timestamp(, 'yyyy-MM-ddTHH:mm:ss.SSSUUU'),,)",
&[×tamp, &name, &val],
)?;
这看起来不太好,因为我必须进行这种向前和向后的字符串转换,我希望能够编写类似
的东西
let name: &str = "hello from rust";
let val: i32 = 123;
let now: DateTime<Utc> = Utc::now();
client.execute(
"INSERT INTO trades VALUES(,,)",
&[&now, &name, &val],
)?;
以这种方式获取时间戳的最佳方式是什么?
编辑:
这是上面第二个例子返回的错误
Error: Error { kind: ToSql(0), cause: Some(WrongType { postgres: Timestamp, rust: "chrono::datetime::DateTime<chrono::offset::utc::Utc>" }) }
我的 cargo.toml
看起来像这样(它为 rust postgres crate 启用了计时功能):
[dependencies]
chrono = "0.4.19"
postgres={version="0.19.0", features=["with-serde_json-1", "with-bit-vec-0_6", "with-chrono-0_4"]}
我认为问题是你的 postgres 模式和你的 Rust 类型不匹配:错误似乎是说你的 postgres 类型是 timestamp
,而你的 rust 类型是 DateTime<Utc>
。
如果您选中 the conversion table,DateTime<Utc>
将转换为 TIMESTAMP WITH TIME ZONE
。转换为 TIMESTAMP
的唯一类型是 NaiveDateTime
和 PrimitiveDateTime
.
根据 ,我需要传递一个 NaiveDateTime
类型才能工作,naive_local
的完整示例如下所示:
use postgres::{Client, NoTls, Error};
use chrono::{Utc};
use std::time::SystemTime;
fn main() -> Result<(), Error> {
let mut client = Client::connect("postgresql://admin:quest@localhost:8812/qdb", NoTls)?;
// Basic query
client.batch_execute("CREATE TABLE IF NOT EXISTS trades (ts TIMESTAMP, date DATE, name STRING, value INT) timestamp(ts);")?;
// Parameterized query
let name: &str = "rust example";
let val: i32 = 123;
let utc = Utc::now();
let sys_time = SystemTime::now();
client.execute(
"INSERT INTO trades VALUES(,,,)",
&[&utc.naive_local(), &sys_time, &name, &val],
)?;
// Prepared statement
let mut txn = client.transaction()?;
let statement = txn.prepare("insert into trades values (,,,)")?;
for value in 0..10 {
let utc = Utc::now();
let sys_time = SystemTime::now();
txn.execute(&statement, &[&utc.naive_local(), &sys_time, &name, &value])?;
}
txn.commit()?;
println!("import finished");
Ok(())
}
我正在使用 rust-postgres 箱来摄取数据。这是一个成功添加行的工作示例:
let name: &str = "hello from rust";
let val: i32 = 123;
let now: DateTime<Utc> = Utc::now();
let timestamp = now.format("%Y-%m-%dT%H:%M:%S%.6f").to_string();
client.execute(
"INSERT INTO trades VALUES(to_timestamp(, 'yyyy-MM-ddTHH:mm:ss.SSSUUU'),,)",
&[×tamp, &name, &val],
)?;
这看起来不太好,因为我必须进行这种向前和向后的字符串转换,我希望能够编写类似
的东西 let name: &str = "hello from rust";
let val: i32 = 123;
let now: DateTime<Utc> = Utc::now();
client.execute(
"INSERT INTO trades VALUES(,,)",
&[&now, &name, &val],
)?;
以这种方式获取时间戳的最佳方式是什么?
编辑:
这是上面第二个例子返回的错误
Error: Error { kind: ToSql(0), cause: Some(WrongType { postgres: Timestamp, rust: "chrono::datetime::DateTime<chrono::offset::utc::Utc>" }) }
我的 cargo.toml
看起来像这样(它为 rust postgres crate 启用了计时功能):
[dependencies]
chrono = "0.4.19"
postgres={version="0.19.0", features=["with-serde_json-1", "with-bit-vec-0_6", "with-chrono-0_4"]}
我认为问题是你的 postgres 模式和你的 Rust 类型不匹配:错误似乎是说你的 postgres 类型是 timestamp
,而你的 rust 类型是 DateTime<Utc>
。
如果您选中 the conversion table,DateTime<Utc>
将转换为 TIMESTAMP WITH TIME ZONE
。转换为 TIMESTAMP
的唯一类型是 NaiveDateTime
和 PrimitiveDateTime
.
根据 NaiveDateTime
类型才能工作,naive_local
的完整示例如下所示:
use postgres::{Client, NoTls, Error};
use chrono::{Utc};
use std::time::SystemTime;
fn main() -> Result<(), Error> {
let mut client = Client::connect("postgresql://admin:quest@localhost:8812/qdb", NoTls)?;
// Basic query
client.batch_execute("CREATE TABLE IF NOT EXISTS trades (ts TIMESTAMP, date DATE, name STRING, value INT) timestamp(ts);")?;
// Parameterized query
let name: &str = "rust example";
let val: i32 = 123;
let utc = Utc::now();
let sys_time = SystemTime::now();
client.execute(
"INSERT INTO trades VALUES(,,,)",
&[&utc.naive_local(), &sys_time, &name, &val],
)?;
// Prepared statement
let mut txn = client.transaction()?;
let statement = txn.prepare("insert into trades values (,,,)")?;
for value in 0..10 {
let utc = Utc::now();
let sys_time = SystemTime::now();
txn.execute(&statement, &[&utc.naive_local(), &sys_time, &name, &value])?;
}
txn.commit()?;
println!("import finished");
Ok(())
}