前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Rust 连接 PostgreSQL 数据库

Rust 连接 PostgreSQL 数据库

作者头像
solenovex
发布2022-03-10 16:51:12
2.7K0
发布2022-03-10 16:51:12
举报
文章被收录于专栏:草根专栏草根专栏

这次,我们使用 postgres 这个 crate 来连接和操作 PostgreSQL 数据库。

创建好项目后,在 cargo.toml 里添加 postgres 的依赖:

7 
8 
9 
10 
[ dependenci es] 
postgres " 
0.19.2"
7 8 9 10 [ dependenci es] postgres " 0.19.2"

首先,导入相关的类型,并创建一个 Person struct:

@ main.rs 6, 
src > @ main.rs > . 
1 
2 
3 
4 
5 
6 
8 
use postgres :: {error :: Error, 
Åderive(Debug)] 
struct Person { 
id: i32, 
name: String, 
data: Option<Vec<u8>>, 
Client, 
NoT1s};
@ main.rs 6, src > @ main.rs > . 1 2 3 4 5 6 8 use postgres :: {error :: Error, Åderive(Debug)] struct Person { id: i32, name: String, data: Option<Vec<u8>>, Client, NoT1s};

再创建 create_db 函数,用来创建数据库和表,它返回一个 Result,里面可能是 Client 或错误:

注意,Client::connect() 函数所接受的连接字符串可以是两种形式的:

10 
11 
12 
13 
14 
15 
16 
17 
18 
19 
20 
21 
22 
23 
24 
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
fn 
create_db() Result<Client, 
Error> { 
let 
let 
let 
let 
let 
let 
let 
let 
" postgres"; 
username 
password 
" postgres" ; 
host 
"localhost"; 
" 5432"; 
port 
database 
" rust2021"; 
conn_str = &format!( 
"postgres://{}{}{}ä){}{}{}{}{}", 
username , 
if password.is_empty() { 
password , 
host, 
port.is_empty() { 
if 
port , 
if database.is_empty() { 
database 
} else 
else { } , 
} else 
client = Client :: connect(conn_str, 
mut 
client.execute("DROP TABLE person" , 
NoT1s)?, 
client. execute( 
"CREATE TABLE person ( 
id 
name 
data 
81], 
Ok(client) 
SERIAL PRIMARY KEY, 
TEXT NOT NULL, 
BYTEA
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 fn create_db() Result<Client, Error> { let let let let let let let let " postgres"; username password " postgres" ; host "localhost"; " 5432"; port database " rust2021"; conn_str = &format!( "postgres://{}{}{}ä){}{}{}{}{}", username , if password.is_empty() { password , host, port.is_empty() { if port , if database.is_empty() { database } else else { } , } else client = Client :: connect(conn_str, mut client.execute("DROP TABLE person" , NoT1s)?, client. execute( "CREATE TABLE person ( id name data 81], Ok(client) SERIAL PRIMARY KEY, TEXT NOT NULL, BYTEA
  • Key-Value 形式。例如:Client::connect("host=localhost user=postgres", NoTls)?; 具体的 key 需要查阅官方文档。
  • URL 形式。本例中使用的是 URL 形式。

一个相对完整的数据库连接字符串 URL 格式是:

postgres://username[:password]@host[:port][/database],其中 password、port、database 都是可选的。所以上面代码中做了相应的判断处理。

Client::connect() 函数的第二个参数用的是 NoTls,为了简单起见,这里我们不使用 TLS。

第 30、32 行,使用 Client 的 execute 方法先删除数据表(如果存在的话),然后再创建 person 表。

最后返回 Client。

接下来,创建 insert_data 函数,来插入一些数据:

44 
45 
46 
48 
49 
50 
51 
52 
53 
54 
55 
56 
57 
58 
59 
60 
61 
62 
63 
64 
fn 
insert_data(client: &mut Client) 9 
let 
let 
Person { 
pl 
id: 
1, 
"Dave" .to_string(), 
name : 
data: None, 
Person { 
id: 
2, 
"Nick" .to_string(), 
name : 
data: None, 
client. execute( 
"INSERT INTO person (id, name, data) 
VALUES ($1, $2, $3), 
8[8p1.id, 8p1.name, 8p1.data, &p2.id, 
Error> { 
. name , 
. data],
44 45 46 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 fn insert_data(client: &mut Client) 9 let let Person { pl id: 1, "Dave" .to_string(), name : data: None, Person { id: 2, "Nick" .to_string(), name : data: None, client. execute( "INSERT INTO person (id, name, data) VALUES ($1, $2, $3), 8[8p1.id, 8p1.name, 8p1.data, &p2.id, Error> { . name , . data],

注意该函数的参数 Client 必须是 mut 的。

再创建一个查询数据的函数:

66 
67 
68 
69 
70 
71 
72 
73 
74 
75 
76 
77 
fn 
get_data(client: 8mut Client) 
let mut persons = Vec :: new(); 
in 
for row 
persons.push(Person { 
id: row.get(ø), 
name: row.get(l), 
data: row.get(2), 
D; 
Ok(persons) 
Result<Vec<Person> , 
id, name, data FROM 
Error> 
person"
66 67 68 69 70 71 72 73 74 75 76 77 fn get_data(client: 8mut Client) let mut persons = Vec :: new(); in for row persons.push(Person { id: row.get(ø), name: row.get(l), data: row.get(2), D; Ok(persons) Result<Vec<Person> , id, name, data FROM Error> person"

这里,我们直接对 Client 的 query 方法返回的结果进行遍历,最后方法返回一个 Vec。

最后,在 main 函数里依次调用这些函数,并把查询结果打印出来:

79 
80 
81 
82 
83 
84 
85 
86 
87 
88 
89 
90 
fn 
main() Result<(), Error> { 
create_db()?; 
let mut 
client 
insert_data(8mut client)? ; 
get_data(&mut client)? 
let 
persons 
persons { 
for p 
print In! ("Person: { : ? } ", 
p);
79 80 81 82 83 84 85 86 87 88 89 90 fn main() Result<(), Error> { create_db()?; let mut client insert_data(8mut client)? ; get_data(&mut client)? let persons persons { for p print In! ("Person: { : ? } ", p);

结果如下:

$ cargo run 
pgdb (D:\Projects\Rust\pgdb) 
Compiling 
dev [unoptimized + debuginfo] target(s) in 1.30s 
Finished 
'target\debug\pgdb. exe 
Running 
Person: Person { id: 1, name: "Dave" 
data: None } 
Person: Person { id: 2, name: "Nick", data: None }
$ cargo run pgdb (D:\Projects\Rust\pgdb) Compiling dev [unoptimized + debuginfo] target(s) in 1.30s Finished 'target\debug\pgdb. exe Running Person: Person { id: 1, name: "Dave" data: None } Person: Person { id: 2, name: "Nick", data: None }

全部代码如下:

代码语言:javascript
复制
use postgres::{error::Error, Client, NoTls};

#[derive(Debug)]
struct Person {
    id: i32,
    name: String,
    data: Option<Vec<u8>>,
}

fn create_db() -> Result<Client, Error> {
    let username = "postgres";
    let password = "postgres";
    let host = "localhost";
    let port = "5432";
    let database = "rust2021";

    let conn_str = &format!(
        "postgres://{}{}{}@{}{}{}{}{}",
        username,
        if password.is_empty() { "" } else { ":" },
        password,
        host,
        if port.is_empty() { "" } else { ":" },
        port,
        if database.is_empty() { "" } else { "/" },
        database
    );
    let mut client = Client::connect(conn_str, NoTls)?;

    let _ = client.execute("DROP TABLE person", &[]);

    client.execute(
        "CREATE TABLE person (
        id      SERIAL PRIMARY KEY,
        name    TEXT NOT NULL,
        data    BYTEA
    )",
        &[],
    )?;

    Ok(client)
}

fn insert_data(client: &mut Client) -> Result<(), Error> {
    let p1 = Person {
        id: 1,
        name: "Dave".to_string(),
        data: None,
    };
    let p2 = Person {
        id: 2,
        name: "Nick".to_string(),
        data: None,
    };

    client.execute(
        "INSERT INTO person (id, name, data)
    VALUES ($1, $2, $3),
    ($4, $5, $6)",
        &[&p1.id, &p1.name, &p1.data, &p2.id, &p2.name, &p2.data],
    )?;

    Ok(())
}

fn get_data(client: &mut Client) -> Result<Vec<Person>, Error> {
    let mut persons = Vec::new();
    for row in client.query("SELECT id, name, data FROM person", &[])? {
        persons.push(Person {
            id: row.get(0),
            name: row.get(1),
            data: row.get(2),
        });
    }

    Ok(persons)
}

fn main() -> Result<(), Error> {
    let mut client = create_db()?;
    insert_data(&mut client)?;

    let persons = get_data(&mut client)?;

    for p in persons {
        println!("Person: {:?}", p);
    }

    Ok(())
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-01-21 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档