Hi, there! Rust が大好き SAmmys だよ!

今日はタイトルの通り、MySQLにDateTime型で格納されている情報をRustでNaiveDateTime形で取り出す内容だよ。
・・・え、それだけ?の内容だけど備忘録として残しておくよ。

前提として、データを取り出す元のテーブルは以下のように作成したんだ。

CREATE TABLE files (
    created_at DATETIME,
    prefix VARCHAR(255),
    name VARCHAR(255),
    INDEX idx_created_at (created_at)
);

そして、RUSTのプログラム本体は以下。(sqlxクレートを使ってるよ)

…(前略)…

let query_result = sqlx::query_as!(
    FileInfo,
    "SELECT * FROM files WHERE name = ?",
    file_name
).fetch_one(&data.db).await;

そして、ここで使用しているFileInfoのStructは以下の通り。

use chrono::{prelude::*, naive::NaiveDate};
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Default)]
pub struct FileInfo {
    pub created_at: NaiveDateTime,
    pub prefix: String,
    pub name: String,
}

そしたらね、エラーとしてこういった内容うが出てきたのさ。

error[E0277]: the trait bound `NaiveDate: std::convert::From<std::option::Option<NaiveDateTime>>` is not satisfied
   --> src/handler.rs:390:40
    |
390 |                       let query_result = sqlx::query_as!(
    |  ________________________________________^
391 | |                         FileInfo,
392 | |                         "SELECT * FROM files WHERE name = ?",
393 | |                         filename
394 | |                     )
    | |_____________________^ the trait `std::convert::From<std::option::Option<NaiveDateTime>>` is not implemented for `NaiveDate`
    |
    = help: the trait `std::convert::From<NaiveDateTime>` is implemented for `NaiveDate`
    = note: required for `std::option::Option<NaiveDateTime>` to implement `Into<NaiveDate>`
    = note: this error originates in the macro `$crate::sqlx_macros::expand_query` which comes from the expansion of the macro `sqlx::query_as` (in Nightly builds, run with -Z macro-backtrace for more info)

Rustからしたら、
「DB に null が入ってるかもしれないんだから、Option<> 付けて null の対応に備えておけよ!」
ってことなんだね。

結局、Struct の宣言を以下に修正すれば終了だったよ、って話。

use chrono::{prelude::*, naive::NaiveDate};
use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Default)]
pub struct FileInfo {
    pub created_at: Option<NaiveDateTime>,
    pub prefix: Option<String>,
    pub name: Option<String>,
}

今回のとは話が逸れるけど、REST API でクライアントからマルチパートアップロードで受け取ったバイナリデータを 6MB ごとにプールさせて AWS の S3 にマルチパートアップロードすることもできたよ。
つまり、メモリが 1 GB のマシンに REST APIサーバーを格納していても、例えば 20 GB のファイルを REST API を経由して S3にマルチパートアップロードアップロードできる、ってことね?
こういう低レイヤーの制御ができるRust、本当に大好き?
それでいてメモリも安全?
それでいて処理も高速?

あー大好きRust!!!

bannerAds