Skip to content

Commit

Permalink
feat(spin_sdk::pg): Improve pg type's conversion in Rust SDK
Browse files Browse the repository at this point in the history
- Add conversion support for: int16, int32, int64, floating32,
floating64, binary, boolean;
- Add support for nullable variants;
- Introduce spin_sdk::pg::Error;

Signed-off-by: Konstantin Shabanov <mail@etehtsea.me>
  • Loading branch information
etehtsea committed Nov 15, 2022
1 parent a4c5b54 commit ae806c0
Show file tree
Hide file tree
Showing 15 changed files with 579 additions and 84 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 4 additions & 12 deletions crates/outbound-pg/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,7 @@ fn convert_data_type(pg_type: &Type) -> DbDataType {
Type::INT2 => DbDataType::Int16,
Type::INT4 => DbDataType::Int32,
Type::INT8 => DbDataType::Int64,
Type::TEXT => DbDataType::Str,
Type::VARCHAR => DbDataType::Str,
Type::TEXT | Type::VARCHAR | Type::BPCHAR => DbDataType::Str,
_ => {
tracing::debug!("Couldn't convert Postgres type {} to WIT", pg_type.name(),);
DbDataType::Other
Expand Down Expand Up @@ -208,17 +207,10 @@ fn convert_entry(row: &Row, index: usize) -> Result<DbValue, tokio_postgres::Err
None => DbValue::DbNull,
}
}
&Type::TEXT => {
let value: Option<&str> = row.try_get(index)?;
&Type::TEXT | &Type::VARCHAR | &Type::BPCHAR => {
let value: Option<String> = row.try_get(index)?;
match value {
Some(v) => DbValue::Str(v.to_owned()),
None => DbValue::DbNull,
}
}
&Type::VARCHAR => {
let value: Option<&str> = row.try_get(index)?;
match value {
Some(v) => DbValue::Str(v.to_owned()),
Some(v) => DbValue::Str(v),
None => DbValue::DbNull,
}
}
Expand Down
21 changes: 21 additions & 0 deletions examples/config-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions examples/http-rust-outbound-http/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions examples/http-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions examples/redis-rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

21 changes: 21 additions & 0 deletions examples/rust-outbound-pg/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion examples/rust-outbound-pg/db/testdata.sql
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ CREATE TABLE articletest (
id integer GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
title varchar(40) NOT NULL,
content text NOT NULL,
authorname varchar(40) NOT NULL
authorname varchar(40) NOT NULL,
coauthor text
);

INSERT INTO articletest (title, content, authorname) VALUES
Expand Down
34 changes: 16 additions & 18 deletions examples/rust-outbound-pg/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
#![allow(dead_code)]
use anyhow::{anyhow, Result};
use anyhow::Result;
use spin_sdk::{
http::{Request, Response},
http_component,
pg,
pg::{self, Decode},
};

// The environment variable set in `spin.toml` that points to the
Expand All @@ -16,22 +16,25 @@ struct Article {
title: String,
content: String,
authorname: String,
coauthor: Option<String>,
}

impl TryFrom<&pg::Row> for Article {
type Error = anyhow::Error;

fn try_from(row: &pg::Row) -> Result<Self, Self::Error> {
let id: i32 = (&row[0]).try_into()?;
let title: String = (&row[1]).try_into()?;
let content: String = (&row[2]).try_into()?;
let authorname: String = (&row[3]).try_into()?;
let id = i32::decode(&row[0])?;
let title = String::decode(&row[1])?;
let content = String::decode(&row[2])?;
let authorname = String::decode(&row[3])?;
let coauthor = Option::<String>::decode(&row[4])?;

Ok(Self {
id,
title,
content,
authorname,
coauthor,
})
}
}
Expand All @@ -51,9 +54,8 @@ fn process(req: Request) -> Result<Response> {
fn read(_req: Request) -> Result<Response> {
let address = std::env::var(DB_URL_ENV)?;

let sql = "SELECT id, title, content, authorname FROM articletest";
let rowset = pg::query(&address, sql, &[])
.map_err(|e| anyhow!("Error executing Postgres query: {:?}", e))?;
let sql = "SELECT id, title, content, authorname, coauthor FROM articletest";
let rowset = pg::query(&address, sql, &[])?;

let column_summary = rowset
.columns
Expand Down Expand Up @@ -89,16 +91,14 @@ fn write(_req: Request) -> Result<Response> {
let address = std::env::var(DB_URL_ENV)?;

let sql = "INSERT INTO articletest (title, content, authorname) VALUES ('aaa', 'bbb', 'ccc')";
let nrow_executed =
pg::execute(&address, sql, &[]).map_err(|_| anyhow!("Error execute pg command"))?;
let nrow_executed = pg::execute(&address, sql, &[])?;

println!("nrow_executed: {}", nrow_executed);

let sql = "SELECT COUNT(id) FROM articletest";
let rowset = pg::query(&address, sql, &[])
.map_err(|e| anyhow!("Error executing Postgres query: {:?}", e))?;
let rowset = pg::query(&address, sql, &[])?;
let row = &rowset.rows[0];
let count: i64 = (&row[0]).try_into()?;
let count = i64::decode(&row[0])?;
let response = format!("Count: {}\n", count);

Ok(http::Response::builder()
Expand All @@ -111,12 +111,10 @@ fn pg_backend_pid(_req: Request) -> Result<Response> {
let sql = "SELECT pg_backend_pid()";

let get_pid = || {
let rowset = pg::query(&address, sql, &[])
.map_err(|e| anyhow!("Error executing Postgres query: {:?}", e))?;

let rowset = pg::query(&address, sql, &[])?;
let row = &rowset.rows[0];

i32::try_from(&row[0])
i32::decode(&row[0])
};

assert_eq!(get_pid()?, get_pid()?);
Expand Down
21 changes: 21 additions & 0 deletions examples/rust-outbound-redis/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions sdk/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ bytes = "1"
form_urlencoded = "1.0"
http = "0.2"
spin-macro = { path = "macro" }
thiserror = "1.0.37"
wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" }
Loading

0 comments on commit ae806c0

Please sign in to comment.