ITPub博客

首页 > 数据库 > 数据库开发技术 > 学习Rust(1): 访问PostgreSQL数据库

学习Rust(1): 访问PostgreSQL数据库

原创 数据库开发技术 作者:数据库杂记 时间:2023-05-18 06:15:00 0 删除 编辑

学习Rust: 访问PostgreSQL数据库

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环境了。

最简单的Hello World

使用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代码,还是挺便利的。

试试Rust访问PG

我们先准备一个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,可以预见的将来,它会派上大用场。




原文作者:数据库杂记;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-04-22

  • 博文量
    276
  • 访问量
    160349