
tag: Rust, 应用开发
最近一段时间,关于编程语言,有两种比较火,逐渐进入广大开发人员的视线。 一个是Rust,另一个是Mojo。前者有两个比较大的动作:Linux内核有一部分采用Rust进行重写,主要是在不损失性能的前提下,提高系统的安全性;另一个是Windows 11,使用Rust重写了部分核心库,除了安全性比较好以外,性能居然还有提升。而Mojo号称把Python的运行效率提升了35000倍。
基于这种发展的架式,这两种开发语言估计很快会占据重要的位置。不多说,小练一把,看看Rust用来访问PostgreSQL是啥样的。如果我预估不错的话,再过两三年时间,这两种语言会应用到越来越多的领域。因为它们的优势越来越明显。
这里就以Linux为例,CentOS7.9。使用终端命令行安装如下:
1$ curl --proto '=https' --tlsv1.2 https://sh.rustup.rs -sSf | sh
执行结果如下:
1info: downloading installer
2Warning: Not enforcing strong cipher suites for TLS, this is potentially less secure
3
4Welcome to Rust!
5..........
6
7Rustup metadata and toolchains will be installed into the Rustup
8home directory, located at:
9
10 /var/lib/pgsql/.rustup
11
12This can be modified with the RUSTUP_HOME environment variable.
13
14The Cargo home directory is located at:
15
16............
17
18Current installation options:
19
20
21 default host triple: x86_64-unknown-linux-gnu
22 default toolchain: stable (default)
23 profile: default
24 modify PATH variable: yes
25
261) Proceed with installation (default)
272) Customize installation
283) Cancel installation
上边选择默认安装: 1就可以了。
1 stable-x86_64-unknown-linux-gnu installed - rustc 1.69.0 (84c898d65 2023-04-16)
2
3
4Rust is installed now. Great!
5
6To get started you may need to restart your current shell.
7This would reload your PATH environment variable to include
8Cargo's bin directory ($HOME/.cargo/bin).
9
10To configure your current shell, run:
11source "$HOME/.cargo/env"
这样,按着它的提示:source ~/.cargo/env 就可以进入Rust环境了。
使用cargo init helloworld,生成一个最简单的应用程序
1[11:21:02-postgres@sean-rh1:/iihero/rust/greeting]$ cargo init helloworld
2 Created binary (application) package
3[11:23:30-postgres@sean-rh1:/iihero/rust/greeting]$ cd helloworld
4[11:23:38-postgres@sean-rh1:/iihero/rust/greeting/helloworld]$ ls
5Cargo.toml src
6[11:23:39-postgres@sean-rh1:/iihero/rust/greeting/helloworld]$ cat src/main.rs
7fn main() {
8 println!("Hello, world!");
9}
进到helloworld子目录,编译: (cargo build)
1[11:24:49-postgres@sean-rh1:/iihero/rust/greeting/helloworld]$ cargo build
2 Compiling helloworld v0.1.0 (/iihero/rust/greeting/helloworld)
3 Finished dev [unoptimized + debuginfo] target(s) in 0.46s
简单执行一下:(cargo run):
从这几个步骤来看,使用cargo来编译执行Rust代码,还是挺便利的。
我们先准备一个PG的后台环境 ,这里用的是PostgreSQL14.7。
1host: localhost
2database: mydb
3user: mydb
4password: test123
你如果是DBA相关人员,这种配置很快就能搞定并拥有。
我们重新建一个module/package:
1[11:37:12-postgres@sean-rh1:/iihero/rust/greeting]$ cargo init pgdemo
2 Created binary (application) package
3
这会生成pgdemo子目录,其基本结构如下:
1[11:37:49-postgres@sean-rh1:/iihero/rust/greeting]$ tree pgdemo
2pgdemo
3├── Cargo.toml
4└── src
5 └── main.rs
61 directory, 2 files
我们可以在Cargo.toml里头定义引入的依赖包,在main.rs里头修改代码实现最终的逻辑。
Cargo.toml:
pgxr 是一个 Rust 的 crate 库,可以实现用 Rust 语言来编写 PostgreSQL 的扩展函数(相当于存储过程)。这次,我们使用 postgres 这个 crate 来连接和操作 PostgreSQL 数据库。这里就采用postgres的仓库好了。顺便提一句:在https://crates.io/search?q=postgres 上边我们能搜到很多PG相关的东西。
1[package]
2name = "pgdemo"
3version = "0.1.0"
4edition = "2021"
5
6# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7
8[dependencies]
9postgres = "0.19.2"
再来看完整的实现代码如下:
1use postgres::{error::Error, Client, NoTls};
2
3#[derive(Debug)]
4struct Customer {
5 id: i32,
6 name: String,
7 data: Option<Vec<u8>>,
8}
9
10fn create_db() -> Result<Client, Error> {
11 let username = "mydb";
12 let password = "test123";
13 let host = "localhost";
14 let port = "5555";
15 let database = "mydb";
16 let conn_str = &format!(
17 "postgres://{}{}{}@{}{}{}{}{}",
18 username,
19 if password.is_empty() { "" } else { ":" },
20 password,
21 host,
22 if port.is_empty() { "" } else { ":" },
23 port,
24 if database.is_empty() { "" } else { "/" },
25 database
26 );
27 let mut client = Client::connect(conn_str, NoTls)?;
28 let _ = client.execute("DROP TABLE IF EXISTS customer", &[]);
29 client.execute(
30 "CREATE TABLE customer (
31 id SERIAL PRIMARY KEY,
32 name TEXT NOT NULL,
33 data BYTEA
34 )", &[], )?;
35 Ok(client)
36}
37
38fn insert_data(client: &mut Client) -> Result<(), Error> {
39 let p1 = Customer {
40 id: 1,
41 name: "Dave".to_string(),
42 data: None,
43 };
44 let p2 = Customer {
45 id: 2,
46 name: "Nick".to_string(),
47 data: None,
48 };
49 client.execute(
50 "INSERT INTO customer (id, name, data) VALUES ($1, $2, $3), ($4, $5, $6)",
51 &[&p1.id, &p1.name, &p1.data, &p2.id, &p2.name, &p2.data],)?;
52 Ok(())
53}
54
55fn get_data(client: &mut Client) -> Result<Vec<Customer>, Error> {
56 let mut customers = Vec::new();
57 for row in client.query("SELECT id, name, data FROM customer", &[])? {
58 customers.push(Customer {
59 id: row.get(0),
60 name: row.get(1),
61 data: row.get(2),
62 });
63 }
64 Ok(customers)
65}
66
67fn main() -> Result<(), Error> {
68 let mut client = create_db()?;
69 insert_data(&mut client)?;
70 let customers = get_data(&mut client)?;
71 for p in customers {
72 println!("Customer: {:?}", p);
73 }
74 Ok(())
75}
代码的逻辑也很清晰:
函数:create_db实现对数据库的连接。最后会创建表customer, 如果表存在,则删除表: "DROP TABLE IF EXISTS customer"
函数:insert_data,实现一个insert语句插入两条记录。
函数:get_data,则实现获取查询customer表的结果,预期是两条记录。
第一次编译(build)效果是这样的:
1[12:13:43-postgres@sean-rh1:/iihero/rust/greeting/pgdemo]$ cargo build
2 Compiling libc v0.2.144
3 Compiling cfg-if v1.0.0
4 Compiling autocfg v1.1.0
5 Compiling typenum v1.16.0
6 Compiling version_check v0.9.4
7 Compiling proc-macro2 v1.0.57
8 Compiling generic-array v0.14.7
9 Compiling unicode-ident v1.0.8
10 Compiling quote v1.0.27
11 Compiling subtle v2.4.1
12 Compiling getrandom v0.2.9
13 Compiling tinyvec_macros v0.1.1
14 Compiling log v0.4.17
15 Compiling futures-core v0.3.28
16 Compiling tinyvec v1.6.0
17 Compiling rand_core v0.6.4
18 Compiling bytes v1.4.0
19 Compiling block-buffer v0.10.4
20 Compiling crypto-common v0.1.6
21 Compiling memchr v2.5.0
22 Compiling digest v0.10.6
23 Compiling ppv-lite86 v0.2.17
24 Compiling pin-project-lite v0.2.9
25 Compiling unicode-normalization v0.1.22
26 Compiling syn v2.0.16
27 Compiling rand_chacha v0.3.1
28 Compiling slab v0.4.8
29 Compiling lock_api v0.4.9
30 Compiling tokio v1.28.1
31 Compiling unicode-bidi v0.3.13
32 Compiling cpufeatures v0.2.7
33 Compiling once_cell v1.17.1
34 Compiling futures-sink v0.3.28
35 Compiling futures-task v0.3.28
36 Compiling parking_lot_core v0.9.7
37 Compiling stringprep v0.1.2
38 Compiling tracing-core v0.1.31
39 Compiling sha2 v0.10.6
40 Compiling rand v0.8.5
41 Compiling mio v0.8.6
42 Compiling hmac v0.12.1
43 Compiling md-5 v0.10.5
44 Compiling socket2 v0.4.9
45 Compiling async-trait v0.1.68
46 Compiling scopeguard v1.1.0
47 Compiling byteorder v1.4.3
48 Compiling futures-util v0.3.28
49 Compiling base64 v0.21.0
50 Compiling siphasher v0.3.10
51 Compiling futures-channel v0.3.28
52 Compiling fallible-iterator v0.2.0
53 Compiling smallvec v1.10.0
54 Compiling phf_shared v0.11.1
55 Compiling postgres-protocol v0.6.5
56 Compiling futures-macro v0.3.28
57 Compiling tracing v0.1.37
58 Compiling pin-utils v0.1.0
59 Compiling parking_lot v0.12.1
60 Compiling postgres-types v0.2.5
61 Compiling phf v0.11.1
62 Compiling socket2 v0.5.3
63 Compiling percent-encoding v2.2.0
64 Compiling tokio-util v0.7.8
65 Compiling tokio-postgres v0.7.8
66 Compiling postgres v0.19.5
67 Compiling pgdemo v0.1.0 (/iihero/rust/greeting/pgdemo)
68 Finished dev [unoptimized + debuginfo] target(s) in 15.67s
运行效果是这样的:
1cargo run
准备花点时间了解并学习Rust,可以预见的将来,它会派上大用场。
原文作者:数据库杂记;如有侵权,请联系管理员删除。