質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

Q&A

解決済

1回答

3375閲覧

RustでMySQLのDATETIMEのデータを表示させたい

apo

総合スコア362

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

Rust

Rustは、MoFoが支援するプログラミング言語。高速性を維持しつつも、メモリ管理を安全に行うことが可能な言語です。同じコンパイル言語であるC言語やC++では困難だったマルチスレッドを実装しやすく、並行性という点においても優れています。

0グッド

0クリップ

投稿2021/04/16 00:28

前提・実現したいこと

下記のMySQLのテーブルをRustで表示させたい。

mysql> show columns from memos; +---------+-----------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +---------+-----------+------+-----+---------+----------------+ | id | mediumint | NO | PRI | NULL | auto_increment | | name | char(30) | YES | | NULL | | | comment | char(50) | YES | | NULL | | | time | datetime | YES | | NULL | | +---------+-----------+------+-----+---------+----------------+

データは次のとおりです。

mysql> select * from memos; +----+----------+---------+---------------------+ | id | name | comment | time | +----+----------+---------+---------------------+ | 6 | taro | kuri | 2021-04-14 12:25:17 | | 7 | Susie | ringo | 2021-04-14 09:43:39 | | 8 | ito | food | 2021-04-14 09:43:20 | | 9 | momotaro | momo | 2021-04-14 12:24:48 | +----+----------+---------+---------------------+

発生している問題・エラーメッセージ

下記のように数値や文字列までは表示できました。

apo@gentoo ~/Documents/project/make/rust/mysql_chrone/sample_proj $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/sample_proj` *** 開始 *** 6 taro kuri 7 Susie ringo 8 ito food 9 momotaro momo *** 終了 ***

ですが日付(DATETIME)が表示できません。

文字列として表示させようとすると、コンパイルは通るのですが下記ようなエラーがでます。

apo@gentoo ~/Documents/project/make/rust/mysql/sample_proj $ cargo run Finished dev [unoptimized + debuginfo] target(s) in 0.02s Running `target/debug/sample_proj` *** 開始 *** thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: DeserializationError(Utf8Error { valid_up_to: 0, error_len: Some(1) })', src/main.rs:36:107 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

該当のソースコード

Rust

1use crate::utils::establish_connection; 2 3use diesel::deserialize::QueryableByName; 4use diesel::mysql::MysqlConnection; 5use diesel::prelude::*; 6use diesel::sql_query; 7 8mod utils; 9 10type DB = diesel::mysql::Mysql; 11 12#[derive(Debug)] 13pub struct Memos { 14 id: i32, 15 name: String, 16 comment: String, 17 time: String, 18} 19 20impl QueryableByName<DB> for Memos { 21 fn build<R: diesel::row::NamedRow<diesel::mysql::Mysql>>(row: &R,) -> diesel::deserialize::Result<Self> { 22 Ok(Memos { 23 id: row.get("id")?, 24 name: row.get("name")?, 25 comment: row.get("comment")?, 26 time: row.get("time")?, 27 } 28 ) 29 } 30} 31 32fn simple_sql() { 33 34 let connection: MysqlConnection = establish_connection(); 35 36 let memos: Vec<Memos> = sql_query("SELECT id, name, comment, time FROM memos",).load(&connection).unwrap(); 37 38 for uu in memos.iter(){ 39 println!("{}\t{}\t{}\t{}", uu.id, uu.name, uu.comment, uu.time); 40 //println!("{}\t{}\t{}", uu.id, uu.name, uu.comment); 41 } 42} 43 44fn main (){ 45 eprintln! ("*** 開始 ***"); 46 simple_sql(); 47 eprintln! ("*** 終了 ***"); 48}

試したこと

Rustで日時を扱うという記事を見て下記のように変更してみましたが、今度はコンパイルできませんでした。

./Cargo.toml

[package] name = "sample_proj" version = "0.1.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] diesel = { version = "*", features = ["mysql"] } chrono = "0.4"

./src/main.rs

use crate::utils::establish_connection; use diesel::deserialize::QueryableByName; use diesel::mysql::MysqlConnection; use diesel::prelude::*; use diesel::sql_query; use chrono::{Utc, Local, DateTime, Date}; mod utils; type DB = diesel::mysql::Mysql; #[derive(Debug)] pub struct Memos { id: i32, name: String, comment: String, //time: String, time: DateTime<Utc>, } impl QueryableByName<DB> for Memos { fn build<R: diesel::row::NamedRow<diesel::mysql::Mysql>>(row: &R,) -> diesel::deserialize::Result<Self> { Ok(Memos { id: row.get("id")?, name: row.get("name")?, comment: row.get("comment")?, time: row.get("time")?, } ) } } fn simple_sql() { let connection: MysqlConnection = establish_connection(); let memos: Vec<Memos> = sql_query("SELECT id, name, comment, time FROM memos",).load(&connection).unwrap(); for uu in memos.iter(){ println!("{}\t{}\t{}\t{}", uu.id, uu.name, uu.comment, uu.time); //println!("{}\t{}\t{}", uu.id, uu.name, uu.comment); } } fn main (){ eprintln! ("*** 開始 ***"); simple_sql(); eprintln! ("*** 終了 ***"); }

コンパイル → エラー

apo@gentoo ~/Documents/project/make/rust/mysql_chrono/sample_proj $ cargo build Compiling sample_proj v0.1.0 (/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj) warning: unused imports: `Date`, `Local` --> src/main.rs:8:19 | 8 | use chrono::{Utc, Local, DateTime, Date}; | ^^^^^ ^^^^ | = note: `#[warn(unused_imports)]` on by default error[E0277]: the trait bound `chrono::DateTime<Utc>: FromSql<_, Mysql>` is not satisfied --> src/main.rs:30:39 | 30 | time: row.get("time")?, | ^^^ the trait `FromSql<_, Mysql>` is not implemented for `chrono::DateTime<Utc>` error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. error: could not compile `sample_proj` To learn more, run the command again with --verbose. apo@gentoo ~/Documents/project/make/rust/mysql_chrono/sample_proj $ cargo build --verbose Fresh autocfg v1.0.1 Fresh tinyvec_macros v0.1.0 Fresh unicode-xid v0.2.1 Fresh matches v0.1.8 Fresh pkg-config v0.3.19 Fresh percent-encoding v1.0.1 Fresh byteorder v1.4.3 Fresh tinyvec v1.2.0 Fresh unicode-bidi v0.3.5 Fresh proc-macro2 v1.0.26 Fresh unicode-normalization v0.1.17 Fresh libc v0.2.93 Fresh num-traits v0.2.14 Fresh quote v1.0.9 Fresh idna v0.1.5 Fresh time v0.1.44 Fresh syn v1.0.69 Fresh url v1.7.2 Fresh mysqlclient-sys v0.2.4 Fresh num-integer v0.1.44 Fresh diesel_derives v1.4.1 Fresh diesel v1.4.6 Fresh chrono v0.4.19 Compiling sample_proj v0.1.0 (/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj) Running `rustc --crate-name sample_proj --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=5109028e9619baef -C extra-filename=-5109028e9619baef --out-dir /home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps -C incremental=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/incremental -L dependency=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps --extern chrono=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps/libchrono-e93bd251cf4961dc.rlib --extern diesel=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps/libdiesel-8bb2074f68278926.rlib -L native=/usr/lib64` warning: unused imports: `Date`, `Local` --> src/main.rs:8:19 | 8 | use chrono::{Utc, Local, DateTime, Date}; | ^^^^^ ^^^^ | = note: `#[warn(unused_imports)]` on by default error[E0277]: the trait bound `chrono::DateTime<Utc>: FromSql<_, Mysql>` is not satisfied --> src/main.rs:30:39 | 30 | time: row.get("time")?, | ^^^ the trait `FromSql<_, Mysql>` is not implemented for `chrono::DateTime<Utc>` error: aborting due to previous error; 1 warning emitted For more information about this error, try `rustc --explain E0277`. error: could not compile `sample_proj` Caused by: process didn't exit successfully: `rustc --crate-name sample_proj --edition=2018 src/main.rs --error-format=json --json=diagnostic-rendered-ansi --crate-type bin --emit=dep-info,link -C embed-bitcode=no -C debuginfo=2 -C metadata=5109028e9619baef -C extra-filename=-5109028e9619baef --out-dir /home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps -C incremental=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/incremental -L dependency=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps --extern chrono=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps/libchrono-e93bd251cf4961dc.rlib --extern diesel=/home/apo/Documents/project/make/rust/mysql_chrono/sample_proj/target/debug/deps/libdiesel-8bb2074f68278926.rlib -L native=/usr/lib64` (exit status: 1)

mysql - Dieselを使用してmySQLデータベースから日時を取得するのサイトのコードも試してみたのですが、コンパイルできませんでした。

補足情報(FW/ツールのバージョンなど)

OS:Gentoo
Cargo:cargo 1.53.0-nightly (65d57e6f3 2021-04-04)
MySQL:mysql Ver 8.0.23 for Linux on x86_64 (Gentoo Linux mysql-8.0.23)

全てのソースコード
String ver
chono ver

ご教示よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

chrono を使えばDBと日時データのやりとりはできますが、いくつか問題点があって実動まで至ってないようですね。以下の3つの作業で動きます。

  1. dieselとchronoの連携の有効化
  2. 適切な日時型の選択
  3. 型推論の補助

dieselとchronoの連携の有効化

Cargo.tomldiesel の項目で featureschrono を加えます。

[dependencies] chrono = "0.4.19" diesel = { version = "1.4.6", features = ["mysql", "chrono"] }

適切な日時型の選択

chronoはかなり正確に日時を表現するライブラリですので扱う側も適切な日時の知識が必要になります。MySQLのdatetimeにはタイムゾーン情報がついていません。一方でchronoの DateTime 型にはタイムゾーン情報がついています。タイムゾーン無しのデータに勝手にタイムゾーンをつけてしまうと意図せず時刻がずれるのでエラーになる設計のようです。
chrono にはタイムゾーンのない NaiveDateTime 型があるのでそちらを使えばMySQLとやりとりできます。

rust

1use chrono::NaiveDateTime; 2 3#[derive(Debug)] 4pub struct Memos { 5 id: i32, 6 name: String, 7 comment: String, 8 // NaiveDateTime型を使う 9 time: NaiveDateTime, 10}

型推論の補助

本来は上記2つで動くはずですが、Rustが型推論に失敗しているようなのでmysqlの Datetime を使うことを教えてあげます。

rust

1impl QueryableByName<DB> for Memos { 2 fn build<R: diesel::row::NamedRow<diesel::mysql::Mysql>>( 3 row: &R, 4 ) -> diesel::deserialize::Result<Self> { 5 Ok(Memos { 6 id: row.get("id")?, 7 name: row.get("name")?, 8 comment: row.get("comment")?, 9 // 型情報を教えてあげる 10 time: row.get::<diesel::mysql::types::Datetime, _>("time")?, 11 }) 12 } 13}

この3つを揃えて動かすと以下のように表示されました。これで意図通りなのではないでしょうか。

*** 開始 *** 1 taro kuri 2021-04-16 04:39:25 2 Susie ringo 2021-04-16 04:39:54 3 ito food 2021-04-16 04:40:04 4 momotaro momo 2021-04-16 04:40:15 *** 終了 ***

参考までに、dieselのGetting Startedを読むともう少し記述が少なくなる機能が紹介さてれいるのでもし知らずに今の書き方をしているなら一読をお勧めします。

補足

DBのセットアップが書かれてなかったので以下のSQLを発行しました。スキーマ test はDBのセットアップ時点で作っています。

sql

1CREATE TABLE memos (id MEDIUMINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY, name CHAR(30), comment CHAR(50), time DATETIME); 2INSERT INTO memos (name, comment, time) VALUES ('taro', 'kuri', now()); 3INSERT INTO memos (name, comment, time) VALUES ('Susie', 'ringo', now()); 4INSERT INTO memos (name, comment, time) VALUES ('ito', 'food', now()); 5INSERT INTO memos (name, comment, time) VALUES ('momotaro', 'momo', now());

投稿2021/04/16 04:47

blackenedgold

総合スコア468

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

apo

2021/04/16 05:34

丁寧なご説明とご回答ありがとうございます。 ご教示の通りに修正したら動きました。 修正済みソースコード:[https://github.com/ringo-apo/rust_mysql_chrono](https://github.com/ringo-apo/rust_mysql_chrono) いくらググッてもblackenedgoldさんのように解説されたサイトは見つけられませんでした。ありがとうございます。 また記述の仕方についても色々と教えて頂きありがとうございます。 試してみます。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問