diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index a6d2d99..86ab147 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -46,12 +46,12 @@ jobs: strategy: matrix: name: - - linux / stable + - Build and run all tests # - macOS / stable # - feature / blocking include: - - name: linux / stable + - name: Build and run all tests features: "--features blocking" # - name: feature / blocking @@ -59,13 +59,12 @@ jobs: # - name: macOS / stable # os: macOS-latest - # test-features: "--features __internal_proxy_sys_no_cache" steps: - name: Checkout uses: actions/checkout@v3 - - name: Install rust + - name: Install Rust uses: dtolnay/rust-toolchain@master with: toolchain: ${{ matrix.rust || 'stable' }} diff --git a/README.md b/README.md index 0e52d49..5aea1de 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -[![experimental](https://github.com/GIScience/badges/raw/master/status/experimental.svg)] +![experimental](https://github.com/GIScience/badges/raw/master/status/experimental.svg) [![main](https://github.com/r3stl355/delta-sharing-rust-client/actions/workflows/main.yml/badge.svg?branch=main)](https://github.com/r3stl355/delta-sharing-rust-client/actions/workflows/main.yml) # Delta Sharing client library for Rust @@ -19,7 +19,8 @@ This is a simple library for Rust to access data published via Delta Sharing. Ha - Clone this repo - Set the `bearerToken` and `endpoint` values in the `config.json` to match your Delta Sharing information -- Run a simple example included with the library: `cargo run --example async`. This example is using an async version of the library. When executed, it will get and display all the data from the first Data Sharing table it finds. For an example using a blocking version of the client, run `cargo run --example blocking --features="delta-sharing/blocking"` +- Run a simple example included with the library: `cargo run --example async`. This example is using an async version of the library. When executed, it will get and display all the data from the first Data Sharing table it finds. +- For an example of using a blocking version of the client to do the same, try `cargo run --example blocking --features=blocking` ## Development diff --git a/examples/async.rs b/examples/async.rs index 01682b6..c2698e3 100644 --- a/examples/async.rs +++ b/examples/async.rs @@ -16,12 +16,22 @@ async fn main() { } else { let share_name = &shares[0].name; println!( - "Found {} shares, expoloring share [{}]", + "Found {} shares, exploring share [{}]", shares.len(), share_name ); let schemas = app.list_schemas(&shares[0]).await.unwrap(); println!("Found {} schemas in share [{}]", schemas.len(), &share_name); + + if schemas.len() == 0 { + let schema_tables = app.list_tables(&schemas[0]).await.unwrap(); + println!( + "Found {} tables in schema [{}]", + schema_tables.len(), + &schemas[0].name + ); + } + let tables = app.list_all_tables(&shares[0]).await.unwrap(); if shares.len() == 0 { println!( diff --git a/tests/blocking.rs b/tests/blocking.rs index 0ae7ead..bc3ab79 100644 --- a/tests/blocking.rs +++ b/tests/blocking.rs @@ -52,7 +52,7 @@ fn list_shares() { shares.len(), 2, "Expected a vector of {}, got {}", + 2, shares.len(), - 2 ); } diff --git a/tests/client.rs b/tests/client.rs index 0e81e3e..b7ed841 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -16,36 +16,120 @@ async fn list_shares() { shares.len(), 2, "Expected {} items, got {}", - shares.len(), - 2 + 2, + shares.len() ); } -// #[cfg(not(feature = "blocking"))] #[tokio::test] async fn list_schemas() { - let share_name = "share_1"; let share = Share { - name: share_name.to_string(), + name: "share_1".to_string(), }; let body = &format!( - r#"{{ "items": [ {{ "name":"schema_1", "share": "{}" }}, {{ "name": "schema_2", "share": "{}" }} ] }}"#, - share_name, share_name + r#"{{ "items": [ {{ "name":"schema_1", "share": "{0}" }}, {{ "name": "schema_2", "share": "{0}" }} ] }}"#, + share.name ); - let app = create_mocked_test_app( - body, - &format!("/shares/{}/schemas", share_name), - method("GET"), - ) - .await; + let url = format!("/shares/{}/schemas", share.name); + let app = create_mocked_test_app(body, &url, method("GET")).await; - let shares = app.client.list_schemas(&share).await.unwrap(); + let schemas = app.client.list_schemas(&share).await.unwrap(); assert_eq!( - shares.len(), + schemas.len(), 2, "Expected {} items, got {}", - shares.len(), - 2 + 2, + schemas.len() + ); +} + +#[tokio::test] +async fn list_tables() { + let schema = Schema { + name: "share_1".to_string(), + share: "schema_1".to_string(), + }; + let body = &format!( + r#"{{ "items": [ {{ "name":"table_1", "share": "{0}", "schema": "{1}" }}, {{ "name": "table_2", "share": "{0}", "schema": "{1}" }} ] }}"#, + schema.share, schema.name + ); + let url = format!("shares/{}/schemas/{}/tables", schema.share, schema.name); + let app = create_mocked_test_app(body, &url, method("GET")).await; + + let tables = app.client.list_tables(&schema).await.unwrap(); + + assert_eq!( + tables.len(), + 2, + "Expected {} items, got {}", + 2, + tables.len() + ); +} + +#[tokio::test] +async fn list_all_tables() { + let share = Share { + name: "share_1".to_string(), + }; + let body = &format!( + r#"{{ "items": [ {{ "name":"table_1", "share": "{0}", "schema": "{1}" }}, {{ "name": "table_2", "share": "{0}", "schema": "{1}" }} ] }}"#, + share.name, "schema_1" + ); + let url = format!("shares/{}/all-tables", share.name); + let app = create_mocked_test_app(body, &url, method("GET")).await; + + let tables = app.client.list_all_tables(&share).await.unwrap(); + + assert_eq!( + tables.len(), + 2, + "Expected {} items, got {}", + 2, + tables.len() + ); +} + +#[tokio::test] +async fn get_table_metadata() { + let table = Table { + name: "table_1".to_string(), + share: "share_1".to_string(), + schema: "schema_1".to_string(), + }; + + let body = r#"{ "protocol":{ "minReaderVersion": 1 } } + { "metaData": { "id": "cf9c9342-b773-4c7b-a217-037d02ffe5d8", "format": { "provider": "parquet" }, "schemaString": "{\"type\":\"struct\",\"fields\":[{\"name\":\"pickup_zip\",\"type\":\"integer\",\"nullable\":true,\"metadata\":{}},{\"name\":\"max_trip_distance\",\"type\":\"double\",\"nullable\":true,\"metadata\":{}}]}", "partitionColumns": [], "configuration": {"conf_1_name": "conf_1_value"}}}"#; + + let url = format!( + "shares/{}/schemas/{}/tables/{}/metadata", + table.share, table.schema, table.name + ); + let app = create_mocked_test_app(body, &url, method("GET")).await; + + let meta = app.client.get_table_metadata(&table).await.unwrap(); + + assert_eq!(meta.protocol.min_reader_version, 1, "Protocol mismatch"); + assert_eq!( + meta.metadata.id, "cf9c9342-b773-4c7b-a217-037d02ffe5d8", + "Metadata ID mismatch" + ); + assert_eq!( + meta.metadata.format.provider, "parquet", + "Metadata format provider mismatch" + ); + assert_eq!( + meta.metadata.name, None, + "Metadata name value should be missing" + ); + assert_eq!( + meta.metadata.partition_columns.len(), + 0, + "There should be no partitions" + ); + assert_eq!( + meta.metadata.configuration["conf_1_name"], "conf_1_value", + "Configuration value expected" ); }