# 使用rust实现的mysql交互接口 **Repository Path**: wang-giteee/Rust_sql ## Basic Information - **Project Name**: 使用rust实现的mysql交互接口 - **Description**: 使用rust实现对数据库的查询添加操作 - **Primary Language**: Rust - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2021-11-15 - **Last Updated**: 2021-11-15 ## Categories & Tags **Categories**: Uncategorized **Tags**: Rust, MySQL ## README # 使用rust实现的mysql交互接口 #### 介绍 使用了rust的mysql外部依赖库与 本地mysql 建立连接,实现了查询,添加功能的接口 #### 安装教程 1. 运行环境说明: ->ubuntu version: 20.04 ->MySql version: 8.0.27-0ubuntu0.20.04.1 (Ubuntu) ->Rust version: cargo 1.55.0 (32da73ab1 2021-08-23) 补充:Rust的环境安装镜像源以及Crate.io镜像源均来自上海交通大学镜像源网站 网址:https://mirrors.sjtug.sjtu.edu.cn/ 镜像源配置: rustup配置文件位置: ~/.bashrc vim ~/.bashrc 内容:(写入) export RUSTUP_DIST_SERVER=https://mirror.sjtu.edu.cn/rust-static export RUSTUP_UPDATE_ROOT=https://mirror.sjtu.edu.cn/rust-static/rustup crate.io配置文件位置: ~/.cargo/config vim ~/.cargo/config 内容: [source] [source.mirror] registry = "https://mirrors.sjtug.sjtu.edu.cn/git/crates.io-index/" [source.crates-io] replace-with = "mirror" 注意!如果出现外部依赖包编译报错,极大可能是由于cargo包和crate.io的镜像源不统一导致 2. 配置数据库 在文件中已经配置了数据库文件menu.sql文件,其中包含了所有需要的表结构以及表中的内容 数据库的端口默认为3306,接下来先创建数据库用户damn hadoop@peryol-ThinkPad-T540p:~$ sudo -i [sudo] hadoop 的密码: root@peryol-ThinkPad-T540p:~# mysql -u root //登录本地root账户 mysql> create user ‘damn’@‘%’ identified by ‘123456’; mysql> grant all privileges on *.* to ‘damn’@‘%’; //创建damn用户 mysql> source .sql文件路径; //导入menu表 mysql> use menu; mysql> show tables; //查看数据库中的表,检验是否导入成功 3. rust环境配置 在经过第二步配置镜像源后在shell中进行指令操作 curl https://sh.rustup.rs -sSf | sh source $HOME/.cargo/env 最后输入rust -V查看版本( V是大写!! ) 如果镜像源选择一致,都是上交大源,那么版本号应该是cargo 1.55.0 4. rust外部依赖包配置 rust部分的代码所需要的外部依赖包已经在mylib文件中的Cargo.toml中全部声明,可以直接运行,无需配置,如果发生错误,请参考步骤一中是否配置了匹配的镜像源网站地址 #### 使用说明 (1).结构体说明 #[derive(Debug, PartialEq, Eq)] pub struct log { //登录账户结构体 pub username:String, //账号 pub password:String, //密码 } #[derive(Debug, PartialEq, Eq)] pub struct cus { //注册账户结构体 pub id:String, //用户id pub name:String, //用户名 pub phone:String, //手机号 pub sex:String, //性别 pub vip:String, //是否为vip pub time:String, //注册时间 pub secret:String, //密码 } #[derive(Debug, PartialEq, Eq)] pub struct order_res { //点菜结构体 pub uid: String, pub mid: String, pub num: String, } #[derive(Debug, PartialEq, Eq)] pub struct order_back { //订单传回结构体 pub mid: String, pub num: String, pub price: String, } #[derive(Debug, PartialEq, Eq)] pub struct id_get { //接收id结构体 pub uid:String, } #[derive(Debug, PartialEq, Eq)] pub struct price_get { //传回菜品价格结构体 pub price:String, } (2).方法说明 use mysql::*; use mysql::prelude::*; extern crate libc; use libc::uint32_t; //默认导入外部包 (2.1) pub extern "C" fn login(login:log) -> bool 作用:为前端提供登录功能,参数是传来的log结构体变量,传回的是bool值 代码如下: #[no_mangle] pub extern "C" fn login(login:log) -> bool{ //登录 let url = "mysql://damn:123456@localhost:3306/menu"; let opts = Opts::from_url(url).unwrap(); let pool = Pool::new(opts).unwrap(); let mut conn = pool.get_conn().unwrap(); //建立连接 let res = conn.query_first("select id,secret from customer where name = '顾客1'") //该函数返回的类型是 Result> //sql语句 .map(|row| { //闭包中select选中的行为参数,对行数据再次进行map并返回值 row.map(|(id, secret)| log { //闭包中行数据的id值和secret值为参数,返回一个log结构体 username:id, password:secret, }) }, ); //使用select查看是否有该数据 match res.unwrap() { //查看select情况 Some(log) => { if log.password==login.password { //密码匹配,登录成功 println!("login success!"); return true; } else { return false; //密码匹配失败,登录不成功 println!("error:wrong password!"); } }, None => { //账户不存在 println!("error:id no found!"); return false; }, } } (2.2) pub extern "C" fn insert_user(customer:Vec) -> bool 作用:为前端提供注册服务,接收传来的cus结构体,返回bool值 代码如下: #[no_mangle] pub extern "C" fn insert_user(customer:Vec) -> bool { //注册 let url = "mysql://damn:123456@localhost:3306/menu"; let opts = Opts::from_url(url).unwrap(); let pool = Pool::new(opts).unwrap(); let mut conn = pool.get_conn().unwrap(); //建立连接 let flag = conn.exec_batch( r"INSERT INTO customer (id, name, phone, sex, vip, time, secret) VALUES (:id, :name, :phone, :sex, :vip, :time, :secret)", //返回类型为Result //sql语句 customer.iter().map(|p| params! { //利用传回结构体中的数据对sql语句进行赋值 "id" => &p.id, "name" => &p.name, "phone" => &p.phone, "sex" => &p.sex, "vip" => &p.vip, "time" => &p.time, "secret" => &p.secret, }) ); match flag { //插入成功(注册成功) Ok(c) => { println!("insert success!"); return true; }, Err(e) => { //注册失败 eprintln!("error:{}",e); return false; }, } } (2.3)pub extern "C" fn insert_order(ord:Vec) -> bool 作用:为前端提供点菜服务,将传回的形参容器中的结构体写入um表内,返回bool 代码如下: #[no_mangle] pub extern "C" fn insert_order(ord:Vec) -> bool { //点菜 let url = "mysql://damn:123456@localhost:3306/um"; let opts = Opts::from_url(url).unwrap(); let pool = Pool::new(opts).unwrap(); let mut conn = pool.get_conn().unwrap(); //建立连接 let flag = conn.exec_batch( r"INSERT INTO um (uid,mid,num) VALUES (:uid, :mid, :num)", //sql语句 ord.iter().map(|p| params! { 在闭包中遍历赋值 "uid" => &p.uid, "mid" => &p.mid, "num" => &p.num, }) ); //返回类型为Result match flag { Ok(c) => { //匹配成功 println!("insert success!"); return true; }, Err(e) => { //匹配失败 eprintln!("error:{}",e); return false; }, } } (2.4) pub extern "C" fn get_order(uid:String) -> Vec 作用:为前端提供获取特定用户订单的功能,传回形参为用户的id,以VEC形式返回对应的订单 代码如下: #[no_mangle] pub extern "C" fn get_order(uid:String) -> Vec { let url = "mysql://damn:123456@localhost:3306/menu"; let opts = Opts::from_url(url).unwrap(); let pool = Pool::new(opts).unwrap(); let mut conn = pool.get_conn().unwrap(); //建立连接 let cli = "select * from um where uid = ".to_string(); let c = cli + &uid ; //拼接sql语句 let um1 = conn.query_map( c, |(uid, mid, num)| { //选取闭包参数进行返回结构体 order_res{uid, mid, num} } ).unwrap(); return um1; //返回订单结构体 } (2.5)pub extern "C" fn get_price(mid:String) -> String 作用:为前端提供获取价格的手段,传回菜品id,以String形式返回对应菜品价格 代码如下: #[no_mangle] pub extern "C" fn get_price(mid:String) -> String { let url = "mysql://damn:123456@localhost:3306/menu"; let opts = Opts::from_url(url).unwrap(); let pool = Pool::new(opts).unwrap(); let mut conn = pool.get_conn().unwrap(); let cli = "select price from menu_res where mid = ".to_string(); let c = cli + &mid ; let res = conn.query_first(c).map(|row|{row.map(|(price)| price_get{price})},); match res.unwrap() { Some(s) => {println!("select success"); return s.price;}, None => {println!("no price"); return "null".to_string();}, } } #### 特技 1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md 2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com) 3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目 4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目 5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help) 6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)