< 返回版块

c5soft 发表于 2020-06-09 23:27

Tags:tiberius,mssql

贴一段代码:

use async_std::net::TcpStream;
use tiberius::{AuthMethod, Client, Config};

#[async_std::main]
async fn main() -> anyhow::Result<()> {
    // Using the builder method to construct the options.
    let mut config = Config::new();
    config.host("127.0.0.1");
    config.port(1433);
    config.database("COVID19");
    // Using SQL Server authentication.
    config.authentication(AuthMethod::sql_server("sa", "1234"));

    // Taking the address from the configuration, using async-std's
    // TcpStream to connect to the server.
    let tcp = TcpStream::connect(config.get_addr()).await?;
    // We'll disable the Nagle algorithm. Buffering is handled
    // internally with a `Sink`.
    tcp.set_nodelay(true)?;

    // Handling TLS, login and other details related to the SQL Server.
    let mut client = Client::connect(config, tcp).await?;

    let stream = client
        .query(r"
        SELECT 姓名,证件号码 FROM 特殊人员;
        SELECT @P1 AS AAA UNION ALL SELECT @P2
        ",
            &[&1, &2],
        )
        .await?;

    //let rows = stream.into_first_result().await.unwrap();
    let rowsets = stream.into_results().await.unwrap();
    //println!("{:?}",rows);
    let rows = rowsets.get(0).unwrap();
    for row in rows {
        //println!("{:?}", row);
        println!(
            "{:?},{:?}",
            row.get::<&str, _>(0).unwrap(),
            row.get::<&str, _>(1).unwrap()
        );
    }

    println!("------------------------");
    let rows = rowsets.get(1).unwrap();
    for row in rows {
        //println!("{:?}", row);
        println!("{:?}", row.get::<i32, _>(0).unwrap());
    }

    Ok(())
}

Ext Link: https://crates.io/crates/tiberius

评论区

写评论
作者 c5soft 2020-06-10 20:52

tiberius 0.4的亮点在于完全采用async/await新语法将0.3重写,并且同时支持tokio与async-std两种runtime。这里做了个测试,通过cfg条件编译,演示tokio两种async-std玩法:

cargo.toml文件

[package]
name = "hello-mssql"
version = "0.1.0"
authors = ["Xander Xiao <xander.xiao@gmail.com>"]
edition = "2018"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
tiberius={version="0.4.2" }
anyhow = "1.0.31"
futures = "0.3.5"

[dependencies.tokio]
version = "0.2"
features = ["full"] 
optional = true

[dependencies.tokio-util]
version="0.3.1"
features=["full"]
optional = true

[dependencies.async-std]
version="1.6.0"
features=["attributes"]
optional = true


[features]
default=["use-async-std"]
use-tokio=["tokio","tokio-util"]
use-async-std=["async-std"]

main.rs文件

#[cfg(feature = "use-async-std")]
use async_std::net::TcpStream;

#[cfg(feature = "use-tokio")]
use tokio::net::TcpStream;
#[cfg(feature = "use-tokio")]
use tokio_util::compat::Tokio02AsyncWriteCompatExt;

use tiberius::{AuthMethod, Client, Config};

#[cfg(feature = "use-async-std")]
#[async_std::main]
async fn main() -> anyhow::Result<()> {
    work().await
}

#[cfg(feature = "use-tokio")]
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    work().await
}

async fn work() -> anyhow::Result<()> {
    // Using the builder method to construct the options.
    let mut config = Config::new();
    config.host("192.168.100.4");
    config.port(1433);
    //config.encryption(EncryptionLevel::Required);
    config.trust_cert();
    config.database("COVID19");
    // Using SQL Server authentication.
    config.authentication(AuthMethod::sql_server("sa", "1234"));

    // Taking the address from the configuration, using async-std's
    // TcpStream to connect to the server.
    let tcp = TcpStream::connect(config.get_addr()).await?;
    // We'll disable the Nagle algorithm. Buffering is handled
    // internally with a `Sink`.
    tcp.set_nodelay(true)?;

    // Handling TLS, login and other details related to the SQL Server.

    #[cfg(feature = "use-async-std")]
    let mut client = Client::connect(config, tcp).await?; //async_std

    #[cfg(feature = "use-tokio")]
    let mut client = Client::connect(config, tcp.compat_write()).await?; //tokio

    //SELECT top 10 姓名,证件编号 FROM 员工信息;
    //SELECT top 10 姓名,证件号码 FROM 特殊人员;
    let stream = client
        .query(
            r#"
        SELECT top 10 bmbh,bmmc FROM zwbmzd;
        SELECT @P1 AS AAA UNION ALL SELECT @P2
        "#,
            &[&1, &2],
        )
        .await?;

    //let rows = stream.into_first_result().await.unwrap();
    let rowsets = stream.into_results().await.unwrap();
    //println!("{:?}",rows);
    let rows = rowsets.get(0).unwrap();
    for row in rows {
        //println!("{:?}", row);
        println!(
            "{:?},{:?}",
            row.get::<&str, _>(0).unwrap(),
            row.get::<&str, _>(1).unwrap()
        );
    }

    println!("------------------------");
    let rows = rowsets.get(1).unwrap();
    for row in rows {
        //println!("{:?}", row);
        println!("{:?}", row.get::<i32, _>(0).unwrap());
    }

    Ok(())
}
作者 c5soft 2020-06-10 15:23

对,在Windows 10 64bit测试,顺利运行。rust 1.44 stable-msvc, stable-gnu两种工具链都顺利运行。要连接远端的数据库,需要启用tls, 这是默认选项。因此cargo.toml中如此配置

[dependencies]
tiberius = {version="0.4.2"}
async-std = {version="1.6.0",features=["attributes"]}
anyhow = "1.0.31"
futures = "0.3.5"

关键的关键是:main.rs中加上这样一句:

config.trust_cert();

Windows版的sql server服务器端tls默认是开启的,在没有配置机构证书的情况下,sql server会使用未经签名的自制证书。查看运行日志C:\Program Files\Microsoft SQL Server\MSSQL11.MSSQLSERVER\MSSQL\Log\ERRORLOG,可以看到这样一个记录:A self-generated certificate was successfully loaded for encryption.

对以下内容的回复:

Mike Tang 2020-06-10 14:49

win下运行?

作者 c5soft 2020-06-09 23:33
[dependencies]
tiberius = {version="0.4.2",default-features=false, features=["chrono"] }
async-std = {version="1.6.0",features=["attributes"]}
anyhow = "1.0.31"
futures = "0.3.5"
1 共 4 条评论, 1 页