データベースから情報を取る方法です。
環境は Postgres のバージョン 11 を使います。またその環境は Docker を用いて以下のコマンドで建てたサーバーを使います。
docker run \
--name postgres \
--detach \
--publish 5432:5432 \
--env POSTGRES_HOST_AUTH_METHOD=trust \
postgres:11準備
動作を見るためにusersというテーブルを作り、その中に適当なデータを入れておきたいと思います。
まずはdiesel_cliでマイグレーションファイルを作ります。名前はcreate_usersとし、以下のコマンドを実行します。実行後migrationsディレクトリ以下に雛形が作られます。
# セットアップがまだの場合
diesel migration setup \
--database-url postgres://postgres:@loccalhost:5432
# diesel.toml が作られる
diesel migration generate create_users \
--database-url postgres://postgres:@loccalhost:5432
# migrations/20xx..._create_users/{up,down}.sql
# が作られたmigrations/20xx..._create_users/up.sqlを以下のように編集します。
-- Your SQL goes here
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(30) NOT NULL,
nickname VARCHAR(30),
age INTEGER NOT NULL,
active BOOLEAN DEFAULT 't' NOT NULL,
created_at TIMESTAMP WITHOUT TIME ZONE NOT NULL
);
INSERT INTO users (name, nickname, age, created_at) VALUES
('foo', 'nickfoo', 20, '2020-04-29T01:17:16.644130000+00:00'),
('bar', null, 20, '2020-04-29T01:18:16.644130000+00:00');usersテーブルの作成と、そのレコードの挿入をしてます。
一応戻せるようにdown.sqlも書いておきます。
-- This file should undo anything in `up.sql`
DROP TABLE IF EXISTS users;できたら以下のコマンドで実行します。
diesel migration runちゃんとデータが入っているか以下で確認します。(jqコマンドを使用します)
psql postgres://postgres:@localhost:5432 \
--tuples-only \
--command \
'select json_agg(users) from users' \
| tr -d '\n+' \
| jq .以下のような出力があれば準備完了です。
[
{
"id": 1,
"name": "foo",
"nickname": "nickfoo",
"age": 20,
"active": true,
"created_at": "2020-04-29T01:17:16.64413"
},
{
"id": 2,
"name": "bar",
"nickname": null,
"age": 20,
"active": true,
"created_at": "2020-04-29T01:18:16.64413"
}
]スキーマの確認
実は上記のdiesel migration run ...した際にスキーマモジュールが自動的に作成されているハズです。
例えば今回はこんな感じで作成されてました。
table! {
users (id) {
id -> Int4,
name -> Varchar,
nickname -> Nullable,
age -> Int4,
active -> Bool,
created_at -> Timestamp,
}
} このファイルはdiesel migration setup ...した際に作られるprint_schema.fileに指定されたパスで作られます。
# デフォルト
[print_schema]
file = "src/schema.rs"この自動作成のモジュールを使うためにsrc/lib.rsを作り以下のようにして、main.rsなどで読み込めるうようにしておきます。またその際table!マクロが解決できるようにdieselにmacro_useしておきます。
#[macro_use]
extern crate diesel;
pub mod schema;このtable!マクロでschema::users::dsl::{users,id,name,...}のようにインポートできるコードが生成されます。
アナログでスキーマモジュールを作る
diesel migrationコマンドを使わないプロジェクトなどで使いたい場合は、自分で手書きて用意しても問題なく動かすことができます。ただしそのパスはdiesel.tomlのprint_schema.fileパス先でなければなりません。
スキーマで使用できる型は以下の通りです。
BigIntBinaryBoolDateDoubleFloatIntegerIntervalNullableNumericSmallIntTextTimeTimestampTinyint
取得レコード用の入れ物(構造体)の作成
SQLのデータを入れれるような構造体を作ります。守る必要のあるルールで、その構造体はQueryableトレイトを継承してなければなりません。このトレイトはderiveで継承できます。
今回の場合構造体はこのようになります。
#[derive(Queryable, Debug)]
pub struct User {
pub id: i32,
pub name: String,
pub nickname: Option,
pub age: i32,
pub active: bool,
pub created_at: chrono::NaiveDateTime
} これをsrc/lib.rsのpub mod schema;の後に追記しておきます。
ここでTimestamp型の扱いに関してですが、chronoというライブラリを使います。これによりCargo.tomlの依存関係を以下のように修正します。dieselのfeaturesにもchronoの追加が必要です。
[dependencies]
diesel = { version = "1.4.4", features = [ "postgres", "chrono" ] }
chrono = "0.4.11"データを取得する
src/main.rsを作り、最初のマイグレーションで挿入したデータを取得してみます。
use diesel::pg::PgConnection;
use diesel::prelude::*;
use ::{schema, User};
const DATABASE_URL: &'static str = "postgres://postgres:@localhost:5432";
fn main() {
let connection =
PgConnection::establish(DATABASE_URL).expect(&format!("Error connecting to {}", DATABASE_URL));
let users = schema::users::dsl::users
.load::(&connection)
.expect("Error loading users");
println!("{:#?}", users);
} cargo runで実行して以下のような結果が出力されれば完了です!
[
User {
id: 1,
name: "foo",
nickname: Some(
"nickfoo",
),
age: 20,
active: true,
created_at: 2020-04-29T01:17:16.644130,
},
User {
id: 2,
name: "bar",
nickname: None,
age: 20,
active: true,
created_at: 2020-04-29T01:18:16.644130,
},
]サンプルコード
動作確認できるコードは nju33-com/get-started-diesel-query に置かれています。