pagetakaBlog

最近リフォームと鳥取県日南町の記事多め。写真、PC、ネット等の話題も

Rust失敗録:SQLで使う「型」でコケて、Copilotに助けてもらう

Rust始めて3カ月の暴走妄想痴呆老害爺です。Linux_mint+MariaDB+Rust+sqlx+tokioでなんとかデータ読み出しできました。その後、失敗がひとつ増え、これを備忘録として残しておくことに...。今回の失敗は、MariaDBからの読出し「文字」型の扱いでした。

前説:これまでに成功したのは、同期/非同期で「整数の読出し1個」

RustでMariaDBを操作したいと思い、同期接続でふたつの整数型を一行読出すことができました。その後、非同期+query_asでできました。顛末は以下のリンクからご確認ください。

Rust失敗録:RDBのSQL文「型」でコケる

前回までに、SQL文で id,valを(i32,i32)で型指定した内容でした。今朝、爺、調子に乗って、一方を文字にしてみました。id,cd を(i32, char)と型指定し、実行...失敗でした。

ココまで読んで「そりゃNGでしょ」「初心者が!」「オメェの実力ならそんなもんだ」とおわかりの方、以下の記事はお読みになる必要はありませぬ..ええ。

今回は株データテーブル使いました。日付、銘柄コード、株価各種などが一行に入ってます。

爺はPython+MariaDBでCHAR、VARCHAR使ってました

Rust以前、爺はPythonでMariaDB触ってました。CHAR、VARCHARなどRDBで指定してました。
今回、RustでSQL文を以前のを型だけ変え使うので、銘柄コード(cd)を読みこむのに「id,cd を(i32, char)」としました。しかし、コンパイル時、NGになりました。エラーがVSCodeターミナルに表示されますが、よくわからぬ状態。爺、こういうときは、自分で考えても無駄なことを自覚してるので、Copilotに尋ねました。

Rust :SQL の文字列型(CHAR/VARCHAR/TEXT)を String で受ける

Rustのエラー文と対応するプログラム部分を、Copilot画面に貼り付けました。「SQL の文字列型(CHAR/VARCHAR/TEXT)は Rust では String で受ける」の旨の返答でした。

それで、「id,cd を(i32, char)」を「id,cd を(i32, String)」へと変更。コンパイル通過し、無事期待する結果に至りました。

Rust+MariaDB:文字を読み出すプログラム

今回、読出し成功したmain.rsとCargo.tomlは以下のとおりです。URLなどはご自身の環境に合わせてください。また、対象テーブルの列設定や必要なら値を入れといてください。

Cargo.toml

main.rs動かすために必要なモジュールは、sqlx、tokioのふたつ。インストール/依存関係確立などは過去記事をご覧ください。

[package] # ↓ ご自身のプロジェクト名に合わせてください
name = "x_proj"
version = "0.1.0"
edition = "2024"

[dependencies]
sqlx = { version = "0.7", features = ["runtime-tokio", "mysql"] }
tokio = { version = "1", features = ["full"] }
main.rs

事前の設定がイロイロ必要です。過去記事などをご参照いただければ..と。なお、読出しは1個の設定です。

use sqlx::mysql::MySqlPoolOptions;

#[tokio::main]
async fn main() ->std::result::Result<(), Box<dyn std::error::Error>>{
    connect_with_jpx()
    .await?;
    Ok(())
}

async fn connect_with_jpx() ->std::result::Result<(), Box<dyn std::error::Error>>{
    println!("RDB 接続します");
    let url ="mysql://user:password@192.168.x.x:3306/db_name";
    // user,password,ip,db_name お使いの環境に合わせてください
   
    let pool = MySqlPoolOptions::new()
        .max_connections(5)
        .connect(url)
        .await?;
    let row =sqlx::query_as::<_, (i32, String) > (
        "SELECT num, cd FROM table_name LIMIT 1"
        )
        .fetch_optional(&pool)
        .await?;
    match row {
        Some((num, cd)) => println!("num:{}, cd:{}", num, cd),
        None => println!("データがありません"),
    }
    Ok(())
}

文字列はStringと言われ、爺、沢登り溯上中入り込む支流をまちがえてたことに気づく

PythonでSQL書いてた記憶がこびりついてた爺です。しかし、Rustでは文字列をStringでうけとるのだと。沢登りしてて、入り込む支流を間違えた感じ...シクシク。なお、「Rust にも char はありますが、1文字の Unicode(4バイト) で、SQL の文字列とは別物」とCopilotが重ねて教えてくれました。

sqlxはコンパイル時に型チェックなどしてくれてるそうです。つまり、沢登りするときの地図携行や装備確認をしてくれてるみたいなものですね。

その他にも、日付、decimalなどをマスターしないと、激流に足踏みするか、断崖絶壁に絶望するか、その手前の深い淵に沈むことになるのか...。

厳格なRustですよね。沢を登り切り目的地に到達するには入り込む支流を間違えてはいけない、というコトですね。でも、支流も現に存在している...。遭難しないよういつもCopilotに助けてもらう爺です。