やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

Rust自習(diesel 1 SQLite3 ORM)

 SQLite3のORMを使ってみる。

成果物

参考

CLIインストール

 libsqlite3-devをインストールする。

$ sudo apt update -y
$ sudo apt upgrade -y
$ sudo apt install -y libsqlite3-dev
  • libsqlite3-dev 3.16.2-5+deb9u1

 diesel_cliをインストールする。

$ cargo install diesel_cli --no-default-features --features sqlite

 dieselコマンドのインストール。SQLite3のみ。mysqlやpostglesqlがなくともエラーにならないよう。

失敗

失敗

 なお、libsqlite3-devをインストールする前にdiesel_cliを入れようとすると以下エラー。35分ほどかかったのに……。

$ cargo install diesel_cli --no-default-features --features sqlite
    Updating crates.io index
  Downloaded diesel_cli v1.4.0
  Downloaded 1 crate (38.5 KB) in 2.42s
  Installing diesel_cli v1.4.0
  Downloaded dotenv v0.10.1
  Downloaded diesel v1.4.2
  Downloaded ansi_term v0.11.0
  Downloaded atty v0.2.13
  Downloaded vec_map v0.8.1
  Downloaded migrations_internals v1.4.0
  Downloaded derive-error-chain v0.10.1
  Downloaded diesel_derives v1.4.0
  Downloaded error-chain v0.10.0
  Downloaded regex v0.2.11
  Downloaded toml v0.4.10
  Downloaded tempfile v3.1.0
  Downloaded quote v0.3.15
  Downloaded syn v0.11.11
  Downloaded backtrace v0.3.33
  Downloaded memchr v2.2.1
  Downloaded spin v0.5.0
  Downloaded rand v0.7.0
  Downloaded synom v0.11.3
  Downloaded regex-syntax v0.5.6
  Downloaded unicode-xid v0.0.4
  Downloaded remove_dir_all v0.5.2
  Downloaded backtrace-sys v0.1.31
  Downloaded rustc-demangle v0.1.15
  Downloaded getrandom v0.1.6
  Downloaded ucd-util v0.1.5
  Downloaded rand_chacha v0.2.1
  Downloaded rand_core v0.5.0
  Downloaded c2-chacha v0.2.2
  Downloaded libsqlite3-sys v0.12.0
  Downloaded ppv-lite86 v0.2.5
  Downloaded pkg-config v0.3.15
   Compiling libc v0.2.60
   Compiling proc-macro2 v0.4.30
   Compiling spin v0.5.0
   Compiling cc v1.0.38
   Compiling unicode-xid v0.1.0
   Compiling syn v0.15.42
   Compiling autocfg v0.1.5
   Compiling memchr v2.2.1
   Compiling pkg-config v0.3.15
   Compiling byteorder v1.3.2
   Compiling ppv-lite86 v0.2.5
   Compiling unicode-xid v0.0.4
   Compiling cfg-if v0.1.9
   Compiling quote v0.3.15
   Compiling serde v1.0.97
   Compiling ucd-util v0.1.5
   Compiling rustc-demangle v0.1.15
   Compiling regex v0.2.11
   Compiling bitflags v1.1.0
   Compiling utf8-ranges v1.0.3
   Compiling unicode-width v0.1.5
   Compiling ansi_term v0.11.0
   Compiling strsim v0.8.0
   Compiling vec_map v0.8.1
   Compiling remove_dir_all v0.5.2
   Compiling lazy_static v1.3.0
   Compiling num-traits v0.2.8
   Compiling num-integer v0.1.41
   Compiling synom v0.11.3
   Compiling libsqlite3-sys v0.12.0
   Compiling regex-syntax v0.5.6
   Compiling textwrap v0.11.0
   Compiling c2-chacha v0.2.2
   Compiling thread_local v0.3.6
   Compiling syn v0.11.11
   Compiling backtrace-sys v0.1.31
   Compiling getrandom v0.1.6
   Compiling atty v0.2.13
   Compiling time v0.1.42
   Compiling aho-corasick v0.6.10
   Compiling quote v0.6.13
   Compiling clap v2.33.0
   Compiling rand_core v0.5.0
   Compiling rand_chacha v0.2.1
   Compiling chrono v0.4.7
   Compiling backtrace v0.3.33
   Compiling rand v0.7.0
   Compiling derive-error-chain v0.10.1
   Compiling error-chain v0.10.0
   Compiling tempfile v3.1.0
   Compiling diesel_derives v1.4.0
   Compiling serde_derive v1.0.97
   Compiling dotenv v0.10.1
   Compiling diesel v1.4.2
   Compiling migrations_internals v1.4.0
   Compiling toml v0.4.10
   Compiling diesel_cli v1.4.0
error: linking with `cc` failed: exit code: 1
  |
  = note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-L" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.0.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.1.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.10.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.11.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.12.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.13.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.14.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.15.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.2.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.3.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.4.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.5.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.6.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.7.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.8.rcgu.o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.diesel.be3hb9y9-cgu.9.rcgu.o" "-o" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a" "/tmp/cargo-installYJ831Z/release/deps/diesel-217ef8fdd531986a.47xb7rqtc09kap61.rcgu.o" "-Wl,--gc-sections" "-pie" "-Wl,-zrelro" "-Wl,-znow" "-Wl,-O1" "-nodefaultlibs" "-L" "/tmp/cargo-installYJ831Z/release/deps" "-L" "/tmp/cargo-installYJ831Z/release/build/backtrace-sys-e0df933a66a64c5e/out" "-L" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib" "-Wl,-Bstatic" "/tmp/cargo-installYJ831Z/release/deps/libtoml-04ac9326068d3458.rlib" "/tmp/cargo-installYJ831Z/release/deps/libtempfile-a3d60fd74bdf3974.rlib" "/tmp/cargo-installYJ831Z/release/deps/librand-d6c0407b109cd0f8.rlib" "/tmp/cargo-installYJ831Z/release/deps/librand_chacha-9ceb36010c0ff6f7.rlib" "/tmp/cargo-installYJ831Z/release/deps/libc2_chacha-a791ac2287878b08.rlib" "/tmp/cargo-installYJ831Z/release/deps/libppv_lite86-c943d5b332ea794c.rlib" "/tmp/cargo-installYJ831Z/release/deps/librand_core-7f55f1b8856a7cb9.rlib" "/tmp/cargo-installYJ831Z/release/deps/libgetrandom-52f278df998ea36b.rlib" "/tmp/cargo-installYJ831Z/release/deps/libremove_dir_all-924a3e76b3805492.rlib" "/tmp/cargo-installYJ831Z/release/deps/libserde-e5ca1ae6660d093f.rlib" "/tmp/cargo-installYJ831Z/release/deps/libmigrations_internals-ee0b2976715b5231.rlib" "/tmp/cargo-installYJ831Z/release/deps/libdotenv-71b1fc4c99c245ab.rlib" "/tmp/cargo-installYJ831Z/release/deps/libregex-3283a5e76314dd6d.rlib" "/tmp/cargo-installYJ831Z/release/deps/libutf8_ranges-246f91a4fc18e2df.rlib" "/tmp/cargo-installYJ831Z/release/deps/libregex_syntax-c5d2c7c9ab7e5c35.rlib" "/tmp/cargo-installYJ831Z/release/deps/libucd_util-da19c86e66cfe047.rlib" "/tmp/cargo-installYJ831Z/release/deps/libthread_local-333ab5b37efe476c.rlib" "/tmp/cargo-installYJ831Z/release/deps/liblazy_static-135d80905fc4088d.rlib" "/tmp/cargo-installYJ831Z/release/deps/libspin-32b0c4e3b554a381.rlib" "/tmp/cargo-installYJ831Z/release/deps/libaho_corasick-7b4218ed66356d4f.rlib" "/tmp/cargo-installYJ831Z/release/deps/libmemchr-5250b50548a0225b.rlib" "/tmp/cargo-installYJ831Z/release/deps/liberror_chain-c8f7dfa84f8d1b9c.rlib" "/tmp/cargo-installYJ831Z/release/deps/libbacktrace-ac7efeb3decf38b1.rlib" "/tmp/cargo-installYJ831Z/release/deps/libbacktrace_sys-8ddf659353586916.rlib" "/tmp/cargo-installYJ831Z/release/deps/libcfg_if-529949ea3b5f3c57.rlib" "/tmp/cargo-installYJ831Z/release/deps/librustc_demangle-bf6a4833ecbfc8c3.rlib" "/tmp/cargo-installYJ831Z/release/deps/libdiesel-0e4ac597d93e0d21.rlib" "/tmp/cargo-installYJ831Z/release/deps/liblibsqlite3_sys-7b363f48d4b3db6b.rlib" "/tmp/cargo-installYJ831Z/release/deps/libbyteorder-0b853709cf063e8e.rlib" "/tmp/cargo-installYJ831Z/release/deps/libclap-4693958ad733d8b4.rlib" "/tmp/cargo-installYJ831Z/release/deps/libvec_map-4248b421bd493f24.rlib" "/tmp/cargo-installYJ831Z/release/deps/libtextwrap-6eda2269cb8b3e85.rlib" "/tmp/cargo-installYJ831Z/release/deps/libunicode_width-ec9279802d78de25.rlib" "/tmp/cargo-installYJ831Z/release/deps/libstrsim-c885d2d4c687e87f.rlib" "/tmp/cargo-installYJ831Z/release/deps/libbitflags-271b14ae9e865219.rlib" "/tmp/cargo-installYJ831Z/release/deps/libatty-19ebc89221ac259e.rlib" "/tmp/cargo-installYJ831Z/release/deps/libansi_term-00dfd8340eda6e0e.rlib" "/tmp/cargo-installYJ831Z/release/deps/libchrono-00b585d1050b6c5a.rlib" "/tmp/cargo-installYJ831Z/release/deps/libnum_integer-20998e444de83918.rlib" "/tmp/cargo-installYJ831Z/release/deps/libnum_traits-cb742c0461a24070.rlib" "/tmp/cargo-installYJ831Z/release/deps/libtime-1e7fb0822177d43a.rlib" "/tmp/cargo-installYJ831Z/release/deps/liblibc-3c0607451f75c7b0.rlib" "-Wl,--start-group" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libstd-2dc1ba48239659d3.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libpanic_unwind-57306b8ed3378a0e.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libbacktrace_sys-54463ae5adae3649.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/librustc_demangle-d99667b199a9875a.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libhashbrown-51f4300e102199f5.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/librustc_std_workspace_alloc-b3ccf1f7737a6a91.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libunwind-157c37a3ceb78853.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liblibc-505bcee45aafb736.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/liballoc-c29abd529ba4452b.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/librustc_std_workspace_core-895383a3232f6572.rlib" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcore-5594cb4f559bc761.rlib" "-Wl,--end-group" "/home/pi/.rustup/toolchains/stable-armv7-unknown-linux-gnueabihf/lib/rustlib/armv7-unknown-linux-gnueabihf/lib/libcompiler_builtins-38e90baf978bc428.rlib" "-Wl,-Bdynamic" "-lsqlite3sqlite3" "-lutil" "-lutil" "-ldl" "-lrt" "-lpthread" "-lgcc_s" "-lc" "-lm" "-lrt" "-lpthread" "-lutil" "-lutil"
  = note: /usr/bin/ld: -lsqlite3 が見つかりません
          collect2: error: ld returned 1 exit status
          

error: aborting due to previous error

error: failed to compile `diesel_cli v1.4.0`, intermediate artifacts can be found at `/tmp/cargo-installYJ831Z`

Caused by:
  Could not compile `diesel_cli`.

To learn more, run the command again with --verbose.

プロジェクト作成

$ cargo new diesel_hello --bin

Cargo.toml

[dependencies]
diesel = { version = "1.4.2", features = ["sqlite"] }
dotenv = "0.14.1"

失敗

失敗

[dependencies]
diesel = { version = "1.4.2", features = ["sqlite"] }
diesel_codegen = { version = "0.16.1", features = ["sqlite"] }
dotenv = "0.14.1"

 実行してダウンロード&コンパイルしたらエラー……。

$ cargo run
    Updating crates.io index
  Downloaded dotenv v0.14.1
  Downloaded diesel_codegen v0.16.1
  Downloaded regex v1.2.0
  Downloaded regex-syntax v0.6.10
  Downloaded diesel_infer_schema v0.16.0
  Downloaded diesel v0.16.0
  Downloaded libsqlite3-sys v0.8.1
error: multiple packages link to native library `sqlite3`, but a native library can be linked only once

package `libsqlite3-sys v0.12.0`
    ... which is depended on by `diesel v1.4.2`
    ... which is depended on by `diesel_hello v0.1.0 (/tmp/work/Rust.Diesel.20190727130150/src/diesel_hello)`
links to native library `sqlite3`

package `libsqlite3-sys v0.8.1`
    ... which is depended on by `diesel v0.16.0`
    ... which is depended on by `diesel_codegen v0.16.1`
    ... which is depended on by `diesel_hello v0.1.0 (/tmp/work/Rust.Diesel.20190727130150/src/diesel_hello)`
also links to native library `sqlite3`

diesel_codegen is dead since diesel 0.99. So do not use it!

diesel_codegenディーゼル0.99以来死んでいる。それでそれを使わないでください!

 diesel1.0.0以上ならdiesel_codegenは使わないらしい。

.env

 diesel環境変数DATABASE_URLにあるDBに接続しようとする。また、.envファイルで環境変数を管理する。よって、以下コードを実行する。

cd diesel_hello
echo DATABASE_URL=./db.sqlite3 > .env

diesel setup

diesel setup

 dieselコマンドでDBをつくる。

Creating migrations directory at: /tmp/work/Rust.Diesel.20190727130150/src/diesel_hello/migrations
Creating database: ./db.sqlite3

 作成されたDBファイルのテーブルを一覧してみる。

$ sqlite3 ./db.sqlite3
SQLite version 3.22.0 2018-01-22 18:45:57
Enter ".help" for usage hints.
sqlite> .tables
__diesel_schema_migrations

マイグレーション

diesel migration generate create_posts

 マイグレーションSQLファイルup.sql, down.sqlが生成される。

$ diesel migration generate create_posts
Creating migrations/2019-07-27-061748_create_posts/up.sql
Creating migrations/2019-07-27-061748_create_posts/down.sql

up.sql

 マイグレーションSQLを書く。

create table posts (
    id integer primary key,
    title text not null,
    body text not null,
    is_published text not null default 'f'
);
create table users (
    id integer primary key,
    name text not null,
    created text not null
);

down.sql

drop table posts;

マイグレーション

diesel migration run
Running migration 2019-07-27-061748_create_posts
$ sqlite3 ./db.sqlite3
sqlite> .tables
__diesel_schema_migrations  posts   

 postsテーブルが増えた。

 あと、schema.rsファイルが生成された。

schema.rs

table! {
    posts (id) {
        id -> Nullable<Integer>,
        title -> Text,
        body -> Text,
        is_published -> Text,
    }
}

ロールバック

diesel migration redo
Rolling back migration 2019-07-27-061748_create_posts
Running migration 2019-07-27-061748_create_posts
$ sqlite3 ./db.sqlite3
sqlite> .tables
__diesel_schema_migrations  posts   

 あれ、テーブルが削除されてないのですが……。

コード

github

lib.rs

#[macro_use]
extern crate diesel;
extern crate dotenv;

pub mod models;
pub mod schema;

use diesel::prelude::*;
use dotenv::dotenv;
use std::env;

pub fn establish_connection() -> SqliteConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
    SqliteConnection::establish(&database_url)
        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
}

models.rs

#[derive(Queryable)]
pub struct Post {
    pub id: i32,
    pub title: String,
    pub body: String,
    pub is_published: bool,
}

 とりあえずビルドは成功した。

失敗

失敗

getting started

lib.rs

#[macro_use]
extern crate diesel;
extern crate dotenv;

use diesel::prelude::*;
use diesel::pg::PgConnection;
use dotenv::dotenv;
use std::env;

pub fn establish_connection() -> PgConnection {
    dotenv().ok();

    let database_url = env::var("DATABASE_URL")
        .expect("DATABASE_URL must be set");
    PgConnection::establish(&database_url)
        .expect(&format!("Error connecting to {}", database_url))
}

 ビルドするもエラー。おい公式、動くコード提示してくれ。

error[E0432]: unresolved import `diesel::pg`
 --> src/lib.rs:6:13
  |
6 | use diesel::pg::PgConnection;
  |             ^^ could not find `pg` in `diesel`

error[E0432]: unresolved import `diesel::pg`
 --> src/lib.rs:6:13
  |
6 | use diesel::pg::PgConnection;
  |             ^^ could not find `pg` in `diesel`

所感

 外部クレートなどで300MB近くある。重すぎ!

対象環境

$ uname -a
Linux raspberrypi 4.19.42-v7+ #1219 SMP Tue May 14 21:20:58 BST 2019 armv7l GNU/Linux

前回まで