Skip to content
This repository has been archived by the owner on Oct 6, 2020. It is now read-only.

Commit

Permalink
CosmosDB - Support for User Defined Functions (#272)
Browse files Browse the repository at this point in the history
* Create - Implemented scaffolding

* add delete to test

* Started example

* fixed add delete responses

* implemented list with stream

* Recycled create for replace

* query returning unexpected json

* query with discriminated union

* migrated to new Document without mandatory id

* Corrected example

* fixed example

* simplified query functions

* fixed README

* fixed e2e tests

* working on e2e test

* completed E2E tests

* simplified consistency

* fixed version

* removed leftover println!
  • Loading branch information
Francesco Cogno authored May 19, 2020
1 parent d65fb04 commit cdef63d
Show file tree
Hide file tree
Showing 44 changed files with 2,251 additions and 297 deletions.
36 changes: 20 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Crate | Docs | Crates.io | Downloads | Downloads@Latest |
-- | -- | -- | -- | -- |
[azure_sdk_auth_aad](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_auth_aad) | [![docs](https://docs.rs/azure_sdk_auth_aad/badge.svg)](https://docs.rs/azure_sdk_auth_aad/0.42.2/azure_sdk_auth_aad) | [![Crate](https://img.shields.io/crates/v/azure_sdk_auth_aad.svg)](https://crates.io/crates/azure_sdk_auth_aad) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_auth_aad.svg)](https://crates.io/crates/azure_sdk_auth_aad) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_auth_aad.svg)](https://crates.io/crates/azure_sdk_auth_aad)
[azure_sdk_core](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_core) | [![docs](https://docs.rs/azure_sdk_core/badge.svg)](https://docs.rs/azure_sdk_core/0.43.2/azure_sdk_core) | [![Crate](https://img.shields.io/crates/v/azure_sdk_core.svg)](https://crates.io/crates/azure_sdk_core) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_core.svg)](https://crates.io/crates/azure_sdk_core) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_core.svg)](https://crates.io/crates/azure_sdk_core)
[azure_sdk_cosmos](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_cosmos) | [![docs](https://docs.rs/azure_sdk_cosmos/badge.svg)](https://docs.rs/azure_sdk_cosmos/0.42.4/azure_sdk_cosmos) | [![Crate](https://img.shields.io/crates/v/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos)
[azure_sdk_cosmos](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_cosmos) | [![docs](https://docs.rs/azure_sdk_cosmos/badge.svg)](https://docs.rs/azure_sdk_cosmos/0.43.0/azure_sdk_cosmos) | [![Crate](https://img.shields.io/crates/v/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_cosmos.svg)](https://crates.io/crates/azure_sdk_cosmos)
[azure_sdk_service_bus](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_service_bus) | [![docs](https://docs.rs/azure_sdk_service_bus/badge.svg)](https://docs.rs/azure_sdk_service_bus/0.44.0/azure_sdk_service_bus) | [![Crate](https://img.shields.io/crates/v/azure_sdk_service_bus.svg)](https://crates.io/crates/azure_sdk_service_bus) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_service_bus.svg)](https://crates.io/crates/azure_sdk_service_bus) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_service_bus.svg)](https://crates.io/crates/azure_sdk_service_bus)
[azure_sdk_storage_account](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_storage_account) | [![docs](https://docs.rs/azure_sdk_storage_account/badge.svg)](https://docs.rs/azure_sdk_storage_account/0.40.4/azure_sdk_storage_account) | [![Crate](https://img.shields.io/crates/v/azure_sdk_storage_account.svg)](https://crates.io/crates/azure_sdk_storage_account) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_storage_account.svg)](https://crates.io/crates/azure_sdk_storage_account) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_storage_account.svg)](https://crates.io/crates/azure_sdk_storage_account)
[azure_sdk_storage_blob](https://github.com/MindFlavor/AzureSDKForRust/tree/master/azure_sdk_storage_blob) | [![docs](https://docs.rs/azure_sdk_storage_blob/badge.svg)](https://docs.rs/azure_sdk_storage_blob/0.43.2/azure_sdk_storage_blob) | [![Crate](https://img.shields.io/crates/v/azure_sdk_storage_blob.svg)](https://crates.io/crates/azure_sdk_storage_blob) | [![cratedown](https://img.shields.io/crates/d/azure_sdk_storage_blob.svg)](https://crates.io/crates/azure_sdk_storage_blob) | [![cratelastdown](https://img.shields.io/crates/dv/azure_sdk_storage_blob.svg)](https://crates.io/crates/azure_sdk_storage_blob)
Expand Down Expand Up @@ -42,7 +42,7 @@ You can find examples in the [```examples```](https://github.com/MindFlavor/Azur
```rust
#[macro_use]
extern crate serde_derive;
// Using the prelude module of the Cosmos crate makes easier to use the Rust Azure SDK for Cosmos
// Using the prelude module of the CosmosDB crate makes easier to use the Rust Azure SDK for Cosmos
// DB.
use azure_sdk_core::prelude::*;
use azure_sdk_cosmos::prelude::*;
Expand All @@ -55,6 +55,7 @@ use std::error::Error;
// work (you can create with this SDK too, check the examples folder for that task).
#[derive(Serialize, Deserialize, Debug)]
struct MySampleStruct<'a> {
id: Cow<'a, str>,
a_string: Cow<'a, str>,
a_number: u64,
a_timestamp: i64,
Expand Down Expand Up @@ -98,14 +99,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("Inserting 10 documents...");
for i in 0..10 {
// define the document.
let document_to_insert = Document::new(
format!("unique_id{}", i), // this is the primary key, AKA "/id".
MySampleStruct {
a_string: Cow::Borrowed("Something here"),
a_number: i * 100, // this is the partition key
a_timestamp: chrono::Utc::now().timestamp(),
},
);
let document_to_insert = Document::new(MySampleStruct {
id: Cow::Owned(format!("unique_id{}", i)),
a_string: Cow::Borrowed("Something here"),
a_number: i * 100, // this is the partition key
a_timestamp: chrono::Utc::now().timestamp(),
});

// insert it!
collection_client
Expand Down Expand Up @@ -138,10 +137,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("\nQuerying documents");
let query_documents_response = collection_client
.query_documents()
.with_query(&("SELECT * FROM A WHERE A.a_number < 600".into()))
.with_query(&("SELECT * FROM A WHERE A.a_number < 600".into())) // there are other ways to construct a query, this is the simplest.
.with_query_cross_partition(true) // this will perform a cross partition query! notice how simple it is!
.execute::<MySampleStruct>()
.await?;
.execute::<MySampleStruct>() // This will make sure the result is our custom struct!
.await?
.into_documents() // queries can return Documents or Raw json (ie without etag, _rid, etc...). Since our query return docs we convert with this function.
.unwrap(); // we know in advance that the conversion to Document will not fail since we SELECT'ed * FROM table

println!(
"Received {} documents!",
Expand All @@ -151,19 +152,22 @@ async fn main() -> Result<(), Box<dyn Error>> {
query_documents_response
.results
.iter()
.for_each(|document| println!("number ==> {}", document.result.a_number));
.for_each(|document| {
println!("number ==> {}", document.result.a_number);
});

// TASK 4
for ref document in query_documents_response.results {
// From our query above we are sure to receive a Document.
println!(
"deleting id == {}, a_number == {}.",
document.document_attributes.id, document.result.a_number
document.result.id, document.result.a_number
);

// to spice the delete a little we use optimistic concurreny
collection_client
.with_document(
&document.document_attributes.id,
&document.result.id,
PartitionKeys::new().push(&document.result.a_number)?,
)
.delete_document()
Expand Down
2 changes: 1 addition & 1 deletion azure_sdk_cosmos/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "azure_sdk_cosmos"
version = "0.42.4"
version = "0.43.0"
description = "Rust wrappers around Microsoft Azure REST APIs - Azure Cosmos DB crate"
readme = "README.md"
authors = ["Francesco Cogno <[email protected]>", "Max Gortman <[email protected]>"]
Expand Down
27 changes: 14 additions & 13 deletions azure_sdk_cosmos/examples/attachments00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ extern crate serde_derive;
// specified in the Document struct below.
#[derive(Serialize, Deserialize, Clone, Debug)]
struct MySampleStruct<'a> {
id: Cow<'a, str>,
a_string: Cow<'a, str>,
a_number: u64,
a_timestamp: i64,
Expand Down Expand Up @@ -41,20 +42,18 @@ async fn main() -> Result<(), Box<dyn Error>> {

let id = format!("unique_id{}", 100);

let doc = Document::new(
id.clone(),
MySampleStruct {
a_string: Cow::Borrowed("Something here"),
a_number: 100,
a_timestamp: chrono::Utc::now().timestamp(),
},
);
let doc = Document::new(MySampleStruct {
id: Cow::Borrowed(&id),
a_string: Cow::Borrowed("Something here"),
a_number: 100,
a_timestamp: chrono::Utc::now().timestamp(),
});

// let's add an entity.
match client
.create_document()
.with_document(&doc)
.with_partition_keys(PartitionKeys::new().push(doc.document_attributes.id())?)
.with_partition_keys(PartitionKeys::new().push(&doc.document.id)?)
.execute()
.await
{
Expand All @@ -67,7 +66,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
};

let mut partition_keys = PartitionKeys::new();
partition_keys.push(doc.document_attributes.id())?;
partition_keys.push(&doc.document.id)?;
let document_client = client.with_document(&id, &partition_keys);

// list attachments
Expand All @@ -79,6 +78,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let attachment_client = document_client.with_attachment(&"myref03");
let resp = attachment_client
.create_reference()
.with_consistency_level((&ret).into())
.with_content_type("image/jpeg")
.with_media(
"https://cdn.pixabay.com/photo/2020/01/11/09/30/abstract-background-4756987__340.jpg",
Expand All @@ -95,7 +95,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let attachment_client = document_client.with_attachment(&"myref03");
let resp = attachment_client
.replace_reference()
.with_consistency_level(session_token.clone())
.with_consistency_level(session_token)
.with_content_type("image/jpeg")
.with_media(
"https://Adn.pixabay.com/photo/2020/01/11/09/30/abstract-background-4756987__340.jpg",
Expand All @@ -107,7 +107,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("deleting");
let resp_delete = attachment_client
.delete()
.with_consistency_level(session_token.clone())
.with_consistency_level((&resp).into())
.execute()
.await?;
println!("delete attachment == {:#?}", resp_delete);
Expand All @@ -117,6 +117,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let attachment_client = document_client.with_attachment(&"slug00");
let resp = attachment_client
.create_slug()
.with_consistency_level((&resp_delete).into())
.with_content_type("text/plain")
.with_body(b"FFFFF")
.execute()
Expand All @@ -127,7 +128,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
println!("deleting");
let resp_delete = attachment_client
.delete()
.with_consistency_level(session_token)
.with_consistency_level((&resp).into())
.execute()
.await?;
println!("delete attachment == {:#?}", resp_delete);
Expand Down
3 changes: 2 additions & 1 deletion azure_sdk_cosmos/examples/database00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

let data = r#"
{
"id": "my_id",
"name": "John Tonno7",
"age": 43,
"phones": [
Expand All @@ -49,7 +50,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
}"#;
let v: Value = serde_json::from_str(data)?;

let document = Document::new("my_id".to_owned(), v);
let document = Document::new(v);
let resp = collection_client
.create_document()
.with_document(&document)
Expand Down
22 changes: 11 additions & 11 deletions azure_sdk_cosmos/examples/document00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use std::error::Error;

#[derive(Serialize, Deserialize, Debug)]
struct MySampleStruct<'a> {
id: Cow<'a, str>,
a_string: Cow<'a, str>,
a_number: u64,
a_timestamp: i64,
Expand Down Expand Up @@ -126,14 +127,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
// Now that we have a database and a collection we can insert
// data in them. Let's create a Document. The only constraint
// is that we need an id and an arbitrary, Serializable type.
let doc = Document::new(
"unique_id100".to_owned(),
MySampleStruct {
a_string: Cow::Borrowed("Something here"),
a_number: 100,
a_timestamp: chrono::Utc::now().timestamp(),
},
);
let doc = Document::new(MySampleStruct {
id: Cow::Owned("unique_id100".to_owned()),
a_string: Cow::Borrowed("Something here"),
a_number: 100,
a_timestamp: chrono::Utc::now().timestamp(),
});

// Now we store the struct in Azure Cosmos DB.
// Notice how easy it is! :)
Expand All @@ -147,7 +146,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let create_document_response = collection_client
.create_document()
.with_document(&doc)
.with_partition_keys(&(&doc.document_attributes.id).into())
.with_partition_keys(&(&doc.document.id).into())
.execute()
.await?;
println!(
Expand All @@ -169,7 +168,7 @@ async fn main() -> Result<(), Box<dyn Error>> {

// Now we get the same document by id.
let get_document_response = collection_client
.with_document(&doc, &(&doc.document_attributes.id).into())
.with_document(&doc.document.id, &(&doc.document.id).into())
.get_document()
.execute::<MySampleStruct>()
.await?;
Expand All @@ -188,7 +187,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
let replace_document_response = collection_client
.replace_document()
.with_document(&doc)
.with_partition_keys(&(&doc.document_attributes.id).into())
.with_document_id(&doc.document.id)
.with_partition_keys(&(&doc.document.id).into())
.with_if_match_condition(IfMatchCondition::Match(&document.etag))
.execute()
.await?;
Expand Down
18 changes: 9 additions & 9 deletions azure_sdk_cosmos/examples/document_entries00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern crate serde_derive;
// specified in the Document struct below.
#[derive(Serialize, Deserialize, Clone, Debug)]
struct MySampleStruct<'a> {
id: Cow<'a, str>,
a_string: Cow<'a, str>,
a_number: u64,
a_timestamp: i64,
Expand Down Expand Up @@ -43,20 +44,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
let client = client.with_collection(&collection_name);

for i in 0u64..5 {
let doc = Document::new(
format!("unique_id{}", i),
MySampleStruct {
a_string: Cow::Borrowed("Something here"),
a_number: i,
a_timestamp: chrono::Utc::now().timestamp(),
},
);
let doc = Document::new(MySampleStruct {
id: Cow::Owned(format!("unique_id{}", i)),
a_string: Cow::Borrowed("Something here"),
a_number: i,
a_timestamp: chrono::Utc::now().timestamp(),
});

// let's add an entity.
client
.create_document()
.with_document(&doc)
.with_partition_keys(PartitionKeys::new().push(doc.document_attributes.id())?)
.with_partition_keys(PartitionKeys::new().push(&doc.document.id)?)
.execute()
.await?;
}
Expand Down Expand Up @@ -136,6 +135,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
.replace_document()
.with_document(&doc.document)
.with_partition_keys(PartitionKeys::new().push(&id)?)
.with_document_id(&id)
.with_consistency_level(ConsistencyLevel::from(&response))
.with_if_match_condition(IfMatchCondition::Match(&etag)) // use optimistic concurrency check
.execute()
Expand Down
20 changes: 10 additions & 10 deletions azure_sdk_cosmos/examples/document_entries01.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ extern crate serde_derive;

#[derive(Serialize, Deserialize, Clone, Debug)]
struct MySampleStruct<'a> {
id: Cow<'a, str>,
a_string: Cow<'a, str>,
a_number: u64,
a_timestamp: i64,
Expand All @@ -32,17 +33,15 @@ async fn main() -> Result<(), Box<dyn Error>> {
let client = client.with_database(&database_name);
let client = client.with_collection(&collection_name);

let mut doc = Document::new(
format!("unique_id{}", 500),
MySampleStruct {
a_string: Cow::Borrowed("Something here"),
a_number: 600,
a_timestamp: chrono::Utc::now().timestamp(),
},
);
let mut doc = Document::new(MySampleStruct {
id: Cow::Owned(format!("unique_id{}", 500)),
a_string: Cow::Borrowed("Something here"),
a_number: 600,
a_timestamp: chrono::Utc::now().timestamp(),
});

let mut partition_keys = PartitionKeys::new();
partition_keys.push(doc.document_attributes.id())?;
partition_keys.push(&doc.document.id)?;

// let's add an entity.
let create_document_response = client
Expand All @@ -58,7 +57,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
create_document_response
);

let document_client = client.with_document(&doc, &partition_keys);
let document_client = client.with_document(&doc.document.id, &partition_keys);

let get_document_response = document_client
.get_document()
Expand Down Expand Up @@ -99,6 +98,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let replace_document_response = client
.replace_document()
.with_document(&doc)
.with_document_id(&doc.document.id)
.with_partition_keys(&partition_keys)
.execute()
.await?;
Expand Down
15 changes: 8 additions & 7 deletions azure_sdk_cosmos/examples/query_document00.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,24 +44,25 @@ async fn main() -> Result<(), Box<dyn Error>> {
let client = client.with_collection(&collection_name);

let query_obj = Query::new(&query);
let respo: QueryDocumentsResponse<MySecondSampleStructOwned> = client

let respo: QueryDocumentsResponse<serde_json::Value> = client
.query_documents()
.with_query(&query_obj)
.with_query_cross_partition(true)
.with_parallelize_cross_partition_query(true)
.with_max_item_count(2)
.with_max_item_count(3)
.execute()
.await?;
println!("as items == {:?}", respo);
println!("as json == {:?}", respo);

let respo: QueryDocumentsResponse<serde_json::Value> = client
let respo: QueryDocumentsResponse<MySecondSampleStructOwned> = client
.query_documents()
.with_query(&query_obj)
.with_query_cross_partition(true)
.with_max_item_count(3)
.with_parallelize_cross_partition_query(true)
.with_max_item_count(2)
.execute()
.await?;
println!("as json == {:?}", respo);
println!("as items == {:?}", respo);

//let ret = client
// .query_documents(
Expand Down
Loading

0 comments on commit cdef63d

Please sign in to comment.