#google-cloud #spanner #gcp #macro-derive #generate #google-api

google-cloud-spanner-derive

Google Cloud Platform spanner 客户端库宏推导

2 个不稳定版本

0.2.0 2023 年 10 月 15 日
0.1.0 2022 年 12 月 2 日

#7 in #spanner

Download history 255/week @ 2024-04-07 4/week @ 2024-04-14 31/week @ 2024-04-21 69/week @ 2024-04-28 19/week @ 2024-05-05 30/week @ 2024-05-12 49/week @ 2024-05-19 9/week @ 2024-05-26 81/week @ 2024-06-02 52/week @ 2024-06-09 46/week @ 2024-06-16 71/week @ 2024-06-23 20/week @ 2024-06-30 13/week @ 2024-07-07 10/week @ 2024-07-14 58/week @ 2024-07-21

每月 101 次下载
用于 nene

MIT 许可证

19KB
206

google-cloud-spanner-derive

用于 google-cloud-spanner 的过程宏。

crates.io

安装

[dependencies]
google-cloud-spanner-derive = <version>

快速入门

表推导

#[derive(Table)] 为以下特性生成实现。

  • TryFromStruct
  • ToStruct
  • TryFrom<Row>
use time::OffsetDateTime;
use google_cloud_spanner::client::Client;
use google_cloud_spanner::mutation::insert_struct;
use google_cloud_spanner::reader::AsyncIterator;
use google_cloud_spanner::statement::Statement;
use google_cloud_spanner_derive::Table;

#[derive(Table, Default)]
pub struct UserCharacter {
    pub user_id: String,
    pub character_id: i64,
    // #[spanner(name=...) is used when the column name does not appear in camel case of the field name
    #[spanner(name="LevelX")]
    pub level: i64,
    #[spanner(commitTimestamp)]
    pub updated_at: OffsetDateTime
}

async fn run(client: &Client) -> Result<Vec<UserCharacter>, anyhow::Error> {
    let user = UserCharacter {
        user_id: "user_id".to_string(),
        ..Default::default()
    };
    client.apply(vec![insert_struct("UserCharacter", user)]).await?;

    let mut tx = client.read_only_transaction().await?;
    let stmt = Statement::new("SELECT * From UserCharacter Limit 10");
    let mut reader = tx.query(stmt).await?;
    let mut result = vec![];
    while let Some(row) = reader.next().await? {
        result.push(row.try_into()?);
    }
    Ok(result)
}

以下是生成的实现。

impl ToStruct for UserCharacter {
    fn to_kinds(&self) -> Kinds {
        vec![
            ("UserId", self.user_id.to_kind()),
            ("CharacterId", self.character_id.to_kind()),
            ("LevelX", self.level.to_kind()),
            ("UpdatedAt", self.updated_at.to_kind()),
        ]
    }

    fn get_types() -> Types {
        vec![
            ("UserId", String::get_type()),
            ("CharacterId", i64::get_type()),
            ("LevelX", i64::get_type()),
            ("UpdatedAt", CommitTimestamp::get_type()),
        ]
    }
}

impl TryFromStruct for UserCharacter {
    fn try_from_struct(s: Struct<'_>) -> Result<Self, RowError> {
        Ok(UserCharacter {
            user_id: s.column_by_name("UserId")?,
            character_id: s.column_by_name("CharacterId")?,
            level: s.column_by_name("LevelX")?,
            updated_at: s.column_by_name("UpdatedAt")?,
        })
    }
}

impl TryFrom<Row> for UserCharacter {
    type Error = RowError;
    fn try_from(s: Row) -> Result<Self, RowError> {
        Ok(UserCharacter {
            user_id: s.column_by_name("UserId")?,
            character_id: s.column_by_name("CharacterId")?,
            level: s.column_by_name("LevelX")?,
            updated_at: s.column_by_name("UpdatedAt")?,
        })
    }
}

查询推导

#[derive(Query)] 为以下特性生成实现。

  • TryFrom<Row>
use google_cloud_spanner::transaction::Transaction;
use google_cloud_spanner::reader::AsyncIterator;
use google_cloud_spanner::statement::Statement;
use google_cloud_spanner_derive::{Table, Query};

#[derive(Table, Default)]
pub struct UserCharacter {
    pub user_id: String,
    pub character_id: i64,
}

#[derive(Table, Default)]
pub struct UserItem {
    pub user_id: String,
    pub item_id: i64,
}

#[derive(Query, Default)]
pub struct UserBundle {
    pub user_id: String,
    pub user_characters: Vec<UserCharacter>,
    #[spanner(name="Items")]
    pub user_items: Vec<UserItem>
}

async fn run(user_id: &str, tx: &mut Transaction) -> Result<Option<UserBundle>, anyhow::Error> {
    let mut stmt = Statement::new("
        SELECT
            UserId,
            ARRAY(SELECT AS STRUCT * FROM UserCharacter WHERE UserId = @UserId) AS UserCharacters,
            ARRAY(SELECT AS STRUCT * FROM UserItem WHERE UserId = @UserId) AS Items,
        From User WHERE UserID = @UserID",
    );
    stmt.add_param("UserID", &user_id);
    let mut reader = tx.query(stmt).await?;
    match reader.next().await? {
        Some(row) => Ok(row.try_into()?),
        None => Ok(None)
    }
}

依赖项

~2MB
~43K SLoC