Rust自習(人称辞典 3)
LIKE
句で絞り込んだレコードをランダム出力する。
成果物
LIKE句
LIKE
句でカンマを含む値にマッチさせたい。SQL文なら以下のような。
sqlite> select * from FirstPersons where (',' || comment || ',') LIKE '%,私的表現,%';
以下パターンにマッチする。
*私的表現*
*,私的表現*
*私的表現,*
*,私的表現,*
コード
これをdieselで書くと以下。
main.rs
let results = personal_pronoun::schema::FirstPersons::dsl::FirstPersons .filter(id.eq(rnd_id as i32) .and(comment.eq("私的表現").or(like("私的表現,%")).or(like("%,私的表現")).or(like("%,私的表現,%"))) )
エラー。
error[E0425]: cannot find function `like` in this scope --> src/main.rs:25:40 | 25 | .and(comment.eq("私的表現").or(like("私的表現,%")).or(like("%,私的表現")).or(like("%,私的表現,%"))) | ^^^^ not found in this scope
調べてみた。
なんと、Nullable<>
だとlike
が使えない……。
SQLのNULLは罠
そもそも、SQLのNULLは諸々の弊害を生み出すようだ。よって全フィールドにNOT NULL
制約したほうがいい。そしてオプション項目ならdefault ''
のようにDEFAULT
制約する。
DB再設計
マイグレーション生成
diesel migration generate recreate_not_null_FirstPersons
FirstPersonsテーブル生成
up.sql
-- 既存のテーブルをリネーム alter table FirstPersons rename to tmp_FirstPersons; -- 新しいテーブルを作成(元々のテーブル名と同じ名前で) create table FirstPersons( id integer not null primary key, value text not null, -- 代表的な表記 ruby text not null default '', -- ふりがな、ルビ comment text not null default '' -- 補足 ); -- レコードを全て移す insert into FirstPersons(id, value, ruby, comment) select id, value, ruby, comment from tmp_FirstPersons; -- 元のテーブルを削除 drop table tmp_FirstPersons;
down.sql
はいいや。
マイグレーション実行
diesel migration run
ロールバック方法
diesel migration redo
確認。変更されている。OK。
$ sqlite3 ./PersonalPronoun.sqlite3 ... sqlite> select * from sqlite_master; ... table|FirstPersons|FirstPersons|7|CREATE TABLE FirstPersons( id integer not null primary key, value text not null, -- 代表的な表記 ruby text not null default '', -- ふりがな、ルビ comment text not null default '' -- 補足 )
マイグレーションを最初からやり直したいとき
PersonalPronoun.sqlite3
ファイルを削除するmigrations/.gitkeep
ファイルを削除するdiesel migration run
コマンドを実行する
一気に最新版になる。
schema.rs
table! { FirstPersons (id) { id -> Integer, value -> Text, ruby -> Text, comment -> Text, } }
models.
#[derive(Queryable)] pub struct FirstPersons { pub id: i32, pub value: String, pub ruby: Option<String>, pub comment: Option<String>, }
Nullable
はなくなったのでOption
を外して以下のようにする。
#[derive(Queryable)] pub struct FirstPersons { pub id: i32, pub value: String, pub ruby: String, pub comment: String, }
main.rs
extern crate diesel; extern crate personal_pronoun; use self::diesel::prelude::*; use self::personal_pronoun::models::*; use self::personal_pronoun::*; use rand::{distributions::{Distribution, Standard},Rng,seq::SliceRandom}; fn main() { use personal_pronoun::schema::FirstPersons::dsl::*; let connection = establish_connection(); let count: i64 = personal_pronoun::schema::FirstPersons::dsl::FirstPersons.count().get_result(&connection).unwrap(); println!("count: {}", count); let mut results = personal_pronoun::schema::FirstPersons::dsl::FirstPersons .filter(comment.eq("私的表現") .or(comment.like("私的表現,%")) .or(comment.like("%,私的表現")) .or(comment.like("%,私的表現,%"))) .load::<self::personal_pronoun::models::FirstPersons>(&connection) .expect("Error loading table."); results.shuffle(&mut rand::thread_rng()); println!("{}: {}", results[0].id, results[0].value); }
ランダム方法を変えねばならない。方法は2つ。
- SQL条件に一致した全レコードを取得し、その中からランダムで取得する(
results.shuffle(&mut rand::thread_rng());
) 参考1,参考2 - SQLite3の
random()
関数を使う
SQL固有のやり方は嫌なのでrustのランダムを使った。
実行
成功!
$ cargo run ... count: 123 7: 儂
対象環境
- Raspbierry pi 3 Model B+
- Raspbian stretch 9.0 2018-11-13
- bash 4.4.12(1)-release
- rustc 1.36.0 (a53f9df32 2019-07-03)
- cargo 1.36.0 (c4fcfb725 2019-05-15)
$ uname -a Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux
前回まで
- Rust自習(じゃんけんゲーム1)
- Rust自習(双方向リスト1)
- Rust自習(単方向リスト1)
- Rust自習(単方向リスト2)
- Rust自習(単方向リスト3)
- Rust自習(単方向リスト4)
- Rust自習(単方向リスト5)
- Rust自習(単方向リスト6)
- Rust自習(単方向リスト7)
- Rust自習(リストのインタフェースを考える)
- Rust自習(連結リスト1)
- Rust自習(連結リスト2)
- Rust自習(連結リスト3)
- Rust自習(連結リスト4)
- Rust自習(連結リストの取得系インタフェース考察)
- Rust自習(連結リスト5)
- Rust自習(連結リストの取得系インタフェース考察2)
- Rust自習(連結リスト6)
- Rust自習(連結リスト7)
- Rust自習(連結リスト8)
- Rust自習(連結リスト9)
- Rust自習(変数名でイテレートする方法)
- Rust自習(iter、iter_mut実装方法)
- Rust自習(連結リスト10)
- Rust自習(rev()実装できず)
- Rust自習(cycle()実装できず)
- Rust自習(じゃんけんゲーム2)
- Rust自習(じゃんけんゲーム3)
- Rust自習(じゃんけんゲーム4)
- Rust自習(じゃんけんゲーム5)
- Rust自習(じゃんけんゲーム6)
- Rust自習(じゃんけんゲーム7)
- Rust自習(じゃんけんゲーム8)
- Rustのアップデート(rustup update)
- Rust自習(SQLite3 1)
- Rust自習(SQLite3 2)
- Rust自習(SQLite3 3)
- Rust自習(日時 1 chrono)
- Rust自習(日時 2 chrono)
- Rust自習(日時 3 chrono)
- Rust自習(日時 4 chrono)
- Rust自習(日時 5 chrono)
- Rust自習(日時 6 chrono)
- Rust自習(日時 7 chrono)
- Rust自習(std::time::SystemTime)
- Rust自習(std::time::Instant)
- Rust自習(std::time::Duration)
- Rust自習(シリアライズ serde 1)
- JSON5とは?
- Rust自習(シリアライズ serde 2 JSON5)
- Rust自習(シリアライズ serde 3 chrono日時型変換)
- Rust自習(diesel 1 SQLite3 ORM)
- Rust自習(diesel 2 SQLite3 ORM)
- Rust自習(diesel 3 SQLite3 ORM)
- Rust自習(diesel 4 SQLite3 ORM)
- Rust自習(diesel 5 SQLite3 ORM)
- Rust自習(diesel 6 SQLite3 ORM)
- Rust自習(diesel 7 SQLite3 ORM serde,chrono)
- Rust自習(diesel 8 SQLite3 ORM serde,chrono)
- Rustで正規表現(regex 1)
- Rustで正規表現(regex 2)
- Rustで正規表現(regex 3)
- Rustで正規表現(regex 4)
- Rustで正規表現(regex 5)
- Rust自習(人称辞典 1)
- Rust自習(人称辞典 2)