#snowflake #data-science #connector #sql-query #dashboard #light

light-snowflake-connector

基于Snowflake REST API的轻量级包装器

2个版本

0.1.1 2024年4月2日
0.1.0 2024年1月1日

290数据库接口

Download history 7/week @ 2024-05-21 1/week @ 2024-06-11

每月59次下载

MIT/Apache

50KB
819

轻量级Snowflake连接器

最小化Snowflake公共REST API的包装器。

Docs Package

  • 易于使用
  • 适用于小型战术查询和点查找,
    • 特别是仪表板和其他交互式用例
    • 请注意,Snowflake的延迟通常 >100ms,因此请仔细设计
  • 设计为不会因大数据集而中断,但也没有针对大数据集进行优化

使用方法

将以下行添加到Cargo.toml

# Cargo.toml
light-snowflake-connector = "0.1.0"
use light_snowflake_connector::{Cell, SnowflakeClient, SnowflakeError};
use light_snowflake_connector::jwt_simple::algorithms::RS256KeyPair;

#[tokio::main]
async fn main() -> Result<(), SnowflakeError> {
    let key_pair = RS256KeyPair::generate(2048)?;
    let config = SnowflakeClient {
        key_pair,
        account: "ACCOUNT".into(),
        user: "USER".into(),
        database: "DB".into(),
        warehouse: "WH".into(),
        role: Some("ROLE".into()),
    };

    let result = config
        .prepare("SELECT * FROM TEST_TABLE WHERE id = ? AND name = ?")
        .add_binding(10)
        .add_binding("Henry")
        .query()
        .await?;

    // Get the first partition of the result, and assert that there is only one partition
    let partition = result.only_partition()?;
    
    // Get the results as a Vec<Vec<Cell>>, which is a tagged enum similar to serde_json::Value
    let cells = partition.cells();
    match &cells[0][0] {
        Cell::Int(x) => println!("Got an integer: {}", x),
        Cell::Varchar(x) => println!("Got a string: {}", x),
        _ => panic!("Got something else"),
    }

    // Get the results as a Vec<Vec<serde_json::Value>>, which is a list of lists of JSON values
    let json_table = partition.json_table();

    // Get the results as a Vec<serde_json::Value>, which is a list of JSON objects
    let json_objects = partition.json_objects();

    Ok(())
}

功能 & 限制

身份验证

  • 密钥对身份验证
  • OAuth,SSO:这是可能的,但尚未实现
  • 用户名/密码:在Snowflake REST API 2.0中不可用

查询

  • 使用 qmark "?" 绑定的预处理语句
    • 不支持其他绑定
  • Rust async 支持(但从Snowflake的角度看是同步的)
  • Snowflake "async" 支持(对于超长时间运行的查询)
  • GET和PUT:不支持Snowflake REST API 2.0
  • Arrow支持:我们正在努力保持依赖关系树小
  • 流式传输支持,以及多个批次

类型

  • 字符串,str
  • i128
  • f64
  • bool
  • 日期,时间,Timestamp_Ntz(NaiveDateTime),Timestamp_Ltz(DateTime;未良好测试,不确定用例)
  • Timestamp_Tz(DateTime)
  • 十进制(dec和rust_decimal具有不同的语义和精度)

隐式类型转换

Snowflake的NUMBER类型是128位(38位十进制数字),但也支持刻度。没有本机Rust类型可以实现这两个功能,所以我们选择了更方便(可能是更常见)的用例

  • 整数转换为i128,这是无损的
  • 浮点数转换为f64,这是有损的
  • 操作是在单元格级别确定的,因此您可以有混合类型的列

这种特定的工作区可以通过使用十进制类型来改进,但有一些关于可用库的问题

  • rust_decimal 是一个纯Rust实现,但它不支持128位数字
  • dec 支持128位数字,但某种方式少了4位十进制精度。此外,它是一个C库的包装器,所以它可能会对WASM用户(例如FaaS)造成下游问题。
  • arrow (此外,arrow2) 支持 128 位数字,但它是一个庞大的依赖项,我们将不得不转向列式数据结构以及不同的 API。

多个批次

此库支持多个批次,这对于流式传输大型结果集非常有用。但是结果以 JSON 格式传输,因此如果高吞吐量是关注点,您应该考虑使用基于 Arrow 的库之一,例如 snowflake-api

与其他 Snowflake 连接器的关系

这是 snowflake-connector 库的分支,并在几个方面有所不同

  • 它返回单元格而不是将数据反序列化为自定义结构体
  • 它不支持十进制类型(因为这很难正确实现)

它与 snowflake-api 的不同之处在于

  • 它只使用文档化的 v2 API,目前该 API 不支持 GET 或 PUT
  • 它根本不使用任何已弃用或未记录的 API
  • 它不需要 Arrow(但它也没有 Arrow 的性能优势)

它与大多数其他语言的 Snowflake 连接器不同之处在于

  • 它不使用 Arrow
  • 它不使用已弃用的 v1 API
  • 它不使用未记录的 API
  • 它不支持 GET 或 PUT
  • 它不支持异步查询
  • 它与 Snowflake 无关,也不受 Snowflake 支持。
  • 它不是任何公司的官方产品,没有任何保证、保修或支持。

依赖项

约 10-22MB
约 349K SLoC