20210611のMySQLに関する記事は5件です。

Rust + Rocket(0.5.0-rc) + dotenv + sqlxでMySQL連携apiサーバをつくる

はじめに 前回の記事でRustでSQLサーバに接続することができたので、次はRocketを使って簡単なapiサーバーを作って見たいと思います。 環境 Ubuntu-20.04 on WSL2 rustc 1.54.0-nghtly(2021-05-28) rocket 0.5.0-rc.1 sqlx 0.5.5 dotenv 0.15 MySQLサーバーは構築済みで、サンプルとしてuserテーブルにid(INT)とname(VARCHAR)カラムがあるものとします。 リクエストにはx-api-key:123456というヘッダを必要とし、http://localhost:8000/allで全件を取得してjsonで返すサーバーをつくります。(公式のサンプルコードをほぼそのまま使っています) サンプルコード Cargo.toml [package] name = "api-server" version = "0.1.0" edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] rocket = { version = "0.5.0-rc.1", features = ["json"] } sqlx = { version = "0.5",default-features = true, features = [ "runtime-async-std-native-tls", "mysql"] } dotenv = "0.15" 今回はdotenvを使ってDBの接続情報等を管理してみます。ついでに簡単なセキュリティー対策としてリクエストにはAPIキーを必須とするため、API_KEYも設定しておきます。 .env MYSQL_HOST="サーバー名" MYSQL_DB="DB名" MYSQL_USER="ユーザー名" MYSQL_PASSWORD="パスワード" API_KEY="123456" 見通しを良くするためルーターとモデルをサブモジュールとして作成します。 src/routes.rc use crate::models::{Userdata,fetch_data}; // main.rcで読み込みます。 use rocket::http::Status; use rocket::request::{Outcome,Request,FromRequest}; use rocket::serde::json::Json; //APIキーの構造体を用意します pub struct ApiKey<'r>(&'r str); //APIキーのエラー時に返すステータスをenumで用意します。 #[derive(Debug)] pub enum ApiKeyError { Missing, Invalid, } #[rocket::async_trait] impl<'r> FromRequest<'r> for ApiKey<'r>{ type Error = ApiKeyError; async fn from_request(req: &'r Request<'_> ) -> Outcome<Self,Self::Error> { // .envから読み込んだAPI_KEYの値とリクエストヘッダの値をチェックします。 fn is_valid(key:&str) -> bool { key == std::env::var("API_KEY").unwrap() } // リクエストヘッダーがなければMissing,リクエストヘッダの値が異なる場合などその他のエラーはInvalidステータスを返します。 match req.headers().get_one("x-api-key") { None => Outcome::Failure((Status::BadRequest, ApiKeyError::Missing)), Some(key) if is_valid(key) => Outcome::Success(ApiKey(key)), Some(_) => Outcome::Failure((Status::BadRequest, ApiKeyError::Invalid)), } } } #[get("/")] pub fn index() -> &'static str { "リクエストにはAPIキーが必要です。" } #[get("/all")] pub async fn all(_key:ApiKey<'_>) -> Json<Vec<Userdata>> { let r= fetch_data().await; let rows = match r { Ok(val) => {val}, Err(e) => {vec![ Userdata {id:0,name:e.to_string()}]} }; Json(rows) } //ちなみに下記のようにするとhttp:localhost:8000/api?id=123&name=fooのようなクエリ文字列が使えます #[get("/search?<id>&<name>")] pub async fn search(_key:ApiKey<'_>,id: u32, name: String) -> Json<Vec<Data1>> { println!("ID:{}-NAME:{}",id,name); } src/models.rc use rocket::serde::{Deserialize,Serialize}; //DBのカラム名と方にあわせて構造体を用意します #[derive(Debug,Serialize,Deserialize,sqlx::FromRow)] pub struct Userdata { pub id:i64, pub name: String } //DBに接続してデータを読み込みます pub async fn fetch_data()->Result<Vec<Userdata>,sqlx::Error> { let opt = sqlx::mysql::MySqlConnectOptions::new() .host(&std::env::var("MYSQL_HOST").unwrap()) .ssl_mode(sqlx::mysql::MySqlSslMode::Disabled) .database(&std::env::var("MYSQL_DB").unwrap()) .username(&std::env::var("MYSQL_USER").unwrap()) .password(&std::env::var("MYSQL_PASSWORD").unwrap()); let pool = sqlx::MySqlPool::connect_with(opt).await?; let query = format!("SELECT id , name from users;"); let rows = sqlx::query_as::<_,Userdata>(&query).fetch_all(&pool).await?; Ok(rows) } src/main.rc #![feature(proc_macro_hygiene,decl_macro)] #[macro_use] extern crate rocket; //上のファイルをサブモジュールとして読み込みます。 mod routes; mod models; use dotenv::dotenv; use routes::{api,search}; #[rocket::main] async fn main() { dotenv().ok(); rocket::build().mount("/",routes![index,all,search]).launch().await; } サーバーを立ち上げます $ cargo run curlで確認してみます。 $ curl -i -H 'x-api-key:123456' http://localhost:8000/all 無事JSONが返ってくればひとまず完成です。 まとめ Rocketは公式のドキュメントも英語ではありますがサンプルが豊富でわかりやすく、デフォルトでasync-awaitに対応するなど「全部入り」なので慣れれば使いやすそうです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GROPU BYする時のGROUP_CONCATの使い方

記事を書くきっかけ 会社の仕事で調べて便利だったので(知らなかった) あとアウトプットが大事って聞いた group_concat GROUP_CONCAT 使い方 今回の仕事で使ったデータをマスクして使用します genba_hatureiテーブル id shain_no name genba date_from date_to 1 10001 Aさん ビル建築 2019-04-01 2020-03-31 2 10002 Bさん 家屋建築 2020-02-01 2020-11-31 3 10003 Cさん 橋建設 2020-04-01 null 4 10001 Aさん 家屋解体 2020-04-01 2020-04-30 5 10002 Bさん アパート建築 2020-12-01 null 6 10001 Aさん 整地 2020-05-01 null 欲しいデータの返却値は以下 shain_no name genba 10001 Aさん 2019-04-01 ~ 2020-03-31 : ビル建築 2020-04-01 ~ 2020-04-30 : 家屋解体 2020-05-01 ~ : 整地 10002 Bさん 2020-02-01 ~ 2020-11-31 : 家屋建築 2020-12-01 ~ : アパート建築 10003 Cさん 2020-04-01 ~ : 橋建設 書いたSQLが以下 SELECT shain_no , name , group_concat( date_from , " ~ " , date_to , " : " , genba separator "\r\n" ) as genba FROM genba_haturei GROUP BY shain_no 記事を書いてみて 最初は現場名だけまとめられれば御の字くらいに思ってましたけど、カンマ区切りで追加できるのが便利で一発でかけてしまった。 今後も便利だなと感じたら記事にしてみようかと思います。備忘録も兼ねて。 参考サイト https://techblog.recochoku.jp/5346 https://dev.mysql.com/doc/refman/5.6/ja/group-by-functions.html#function_group-concat
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

MySQL select句の表示条件に括弧を付ける

目的 select句を用いてレコードの情報を出力する際の条件に括弧を付ける方法をメモ的にまとめる 困り事 下記のようなSQLを記載して実行したが思うような結果が得られなかった。 select * from users where admin_flag = 1 and test_user_flag = 1 or master_user_flag = 1; 上記のSQLを記載したときは下記の条件のレコード情報を取得したかった。 usersテーブルのadmin_flagカラムの値が1、かつ test_user_flagカラムの値が1か、master_user_flagが1のレコード情報 方法 下記のように記載することで欲しい情報が取得できた。 select * from users where admin_flag = 1 and (test_user_flag = 1 or master_user_flag = 1); test_user_flagが1かmaster_user_flagが1のレコードがほしいので当該条件部分を括弧でくくった。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

M1 Mac でmysqlインストールのエラー ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries

M1 Macでdocker-composeをするときにmysqlのインストールに失敗するとき。 Status: Downloaded newer image for nginx:latest Pulling db (mysql:5.7)... 5.7: Pulling from library/mysql ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries このようなエラーが出る。 ERROR: no matching manifest for linux/arm64/v8 in the manifest list entries デフォルトでlinux/arm64/v8のmysqlを探しに行って見つからずにエラーを吐いているようだ。 対処法 docker-compose.ymlにplatformを指定して再度docker-composeをする。 db: image: mysql:5.7 platform: linux/x86_64 platform: linux/x86_64 をDBの箇所に指定してあげればエラー無くインストールが完了する。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CakePHP3のクエリービルダーでUSE INDEXを使いたい

前提 CakePHP 3系 MySQL 5.7 CakePHPのクエリービルダーを使ってSQLに USE INDEX (カラム名) を追加したい。 公式ドキュメントを確認したがクエリビルダーのページに記載はなかった。 対応方法 from句に記載する SampleController.php $articles = $this->Articles->find() ->from('articles Articles USE INDEX (category)') //'テーブル名 モデル名 USE INDEX (INDEX名)' ->where(['category' => 'test']) ->toArray(); 以下のようなSQLが発行されます。 use_index.sql SELECT Articles.id AS `Articles__id`, FROM articles Articles USE INDEX (category) WHERE Articles.category = test 参考 CakePHP2より前のバージョンではまた別の方法を使っていたようです。
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む