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

Commit cdef63d

Browse files
author
Francesco Cogno
authored
CosmosDB - Support for User Defined Functions (#272)
* 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!
1 parent d65fb04 commit cdef63d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+2251
-297
lines changed

README.md

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ Crate | Docs | Crates.io | Downloads | Downloads@Latest |
1313
-- | -- | -- | -- | -- |
1414
[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)
1515
[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)
16-
[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)
16+
[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)
1717
[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)
1818
[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)
1919
[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)
@@ -42,7 +42,7 @@ You can find examples in the [```examples```](https://github.com/MindFlavor/Azur
4242
```rust
4343
#[macro_use]
4444
extern crate serde_derive;
45-
// Using the prelude module of the Cosmos crate makes easier to use the Rust Azure SDK for Cosmos
45+
// Using the prelude module of the CosmosDB crate makes easier to use the Rust Azure SDK for Cosmos
4646
// DB.
4747
use azure_sdk_core::prelude::*;
4848
use azure_sdk_cosmos::prelude::*;
@@ -55,6 +55,7 @@ use std::error::Error;
5555
// work (you can create with this SDK too, check the examples folder for that task).
5656
#[derive(Serialize, Deserialize, Debug)]
5757
struct MySampleStruct<'a> {
58+
id: Cow<'a, str>,
5859
a_string: Cow<'a, str>,
5960
a_number: u64,
6061
a_timestamp: i64,
@@ -98,14 +99,12 @@ async fn main() -> Result<(), Box<dyn Error>> {
9899
println!("Inserting 10 documents...");
99100
for i in 0..10 {
100101
// define the document.
101-
let document_to_insert = Document::new(
102-
format!("unique_id{}", i), // this is the primary key, AKA "/id".
103-
MySampleStruct {
104-
a_string: Cow::Borrowed("Something here"),
105-
a_number: i * 100, // this is the partition key
106-
a_timestamp: chrono::Utc::now().timestamp(),
107-
},
108-
);
102+
let document_to_insert = Document::new(MySampleStruct {
103+
id: Cow::Owned(format!("unique_id{}", i)),
104+
a_string: Cow::Borrowed("Something here"),
105+
a_number: i * 100, // this is the partition key
106+
a_timestamp: chrono::Utc::now().timestamp(),
107+
});
109108

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

146147
println!(
147148
"Received {} documents!",
@@ -151,19 +152,22 @@ async fn main() -> Result<(), Box<dyn Error>> {
151152
query_documents_response
152153
.results
153154
.iter()
154-
.for_each(|document| println!("number ==> {}", document.result.a_number));
155+
.for_each(|document| {
156+
println!("number ==> {}", document.result.a_number);
157+
});
155158

156159
// TASK 4
157160
for ref document in query_documents_response.results {
161+
// From our query above we are sure to receive a Document.
158162
println!(
159163
"deleting id == {}, a_number == {}.",
160-
document.document_attributes.id, document.result.a_number
164+
document.result.id, document.result.a_number
161165
);
162166

163167
// to spice the delete a little we use optimistic concurreny
164168
collection_client
165169
.with_document(
166-
&document.document_attributes.id,
170+
&document.result.id,
167171
PartitionKeys::new().push(&document.result.a_number)?,
168172
)
169173
.delete_document()

azure_sdk_cosmos/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "azure_sdk_cosmos"
3-
version = "0.42.4"
3+
version = "0.43.0"
44
description = "Rust wrappers around Microsoft Azure REST APIs - Azure Cosmos DB crate"
55
readme = "README.md"
66
authors = ["Francesco Cogno <[email protected]>", "Max Gortman <[email protected]>"]

azure_sdk_cosmos/examples/attachments00.rs

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ extern crate serde_derive;
1313
// specified in the Document struct below.
1414
#[derive(Serialize, Deserialize, Clone, Debug)]
1515
struct MySampleStruct<'a> {
16+
id: Cow<'a, str>,
1617
a_string: Cow<'a, str>,
1718
a_number: u64,
1819
a_timestamp: i64,
@@ -41,20 +42,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
4142

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

44-
let doc = Document::new(
45-
id.clone(),
46-
MySampleStruct {
47-
a_string: Cow::Borrowed("Something here"),
48-
a_number: 100,
49-
a_timestamp: chrono::Utc::now().timestamp(),
50-
},
51-
);
45+
let doc = Document::new(MySampleStruct {
46+
id: Cow::Borrowed(&id),
47+
a_string: Cow::Borrowed("Something here"),
48+
a_number: 100,
49+
a_timestamp: chrono::Utc::now().timestamp(),
50+
});
5251

5352
// let's add an entity.
5453
match client
5554
.create_document()
5655
.with_document(&doc)
57-
.with_partition_keys(PartitionKeys::new().push(doc.document_attributes.id())?)
56+
.with_partition_keys(PartitionKeys::new().push(&doc.document.id)?)
5857
.execute()
5958
.await
6059
{
@@ -67,7 +66,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
6766
};
6867

6968
let mut partition_keys = PartitionKeys::new();
70-
partition_keys.push(doc.document_attributes.id())?;
69+
partition_keys.push(&doc.document.id)?;
7170
let document_client = client.with_document(&id, &partition_keys);
7271

7372
// list attachments
@@ -79,6 +78,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
7978
let attachment_client = document_client.with_attachment(&"myref03");
8079
let resp = attachment_client
8180
.create_reference()
81+
.with_consistency_level((&ret).into())
8282
.with_content_type("image/jpeg")
8383
.with_media(
8484
"https://cdn.pixabay.com/photo/2020/01/11/09/30/abstract-background-4756987__340.jpg",
@@ -95,7 +95,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
9595
let attachment_client = document_client.with_attachment(&"myref03");
9696
let resp = attachment_client
9797
.replace_reference()
98-
.with_consistency_level(session_token.clone())
98+
.with_consistency_level(session_token)
9999
.with_content_type("image/jpeg")
100100
.with_media(
101101
"https://Adn.pixabay.com/photo/2020/01/11/09/30/abstract-background-4756987__340.jpg",
@@ -107,7 +107,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
107107
println!("deleting");
108108
let resp_delete = attachment_client
109109
.delete()
110-
.with_consistency_level(session_token.clone())
110+
.with_consistency_level((&resp).into())
111111
.execute()
112112
.await?;
113113
println!("delete attachment == {:#?}", resp_delete);
@@ -117,6 +117,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
117117
let attachment_client = document_client.with_attachment(&"slug00");
118118
let resp = attachment_client
119119
.create_slug()
120+
.with_consistency_level((&resp_delete).into())
120121
.with_content_type("text/plain")
121122
.with_body(b"FFFFF")
122123
.execute()
@@ -127,7 +128,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
127128
println!("deleting");
128129
let resp_delete = attachment_client
129130
.delete()
130-
.with_consistency_level(session_token)
131+
.with_consistency_level((&resp).into())
131132
.execute()
132133
.await?;
133134
println!("delete attachment == {:#?}", resp_delete);

azure_sdk_cosmos/examples/database00.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
4040

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

52-
let document = Document::new("my_id".to_owned(), v);
53+
let document = Document::new(v);
5354
let resp = collection_client
5455
.create_document()
5556
.with_document(&document)

azure_sdk_cosmos/examples/document00.rs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use std::error::Error;
1010

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

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

170169
// Now we get the same document by id.
171170
let get_document_response = collection_client
172-
.with_document(&doc, &(&doc.document_attributes.id).into())
171+
.with_document(&doc.document.id, &(&doc.document.id).into())
173172
.get_document()
174173
.execute::<MySampleStruct>()
175174
.await?;
@@ -188,7 +187,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
188187
let replace_document_response = collection_client
189188
.replace_document()
190189
.with_document(&doc)
191-
.with_partition_keys(&(&doc.document_attributes.id).into())
190+
.with_document_id(&doc.document.id)
191+
.with_partition_keys(&(&doc.document.id).into())
192192
.with_if_match_condition(IfMatchCondition::Match(&document.etag))
193193
.execute()
194194
.await?;

azure_sdk_cosmos/examples/document_entries00.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ extern crate serde_derive;
1616
// specified in the Document struct below.
1717
#[derive(Serialize, Deserialize, Clone, Debug)]
1818
struct MySampleStruct<'a> {
19+
id: Cow<'a, str>,
1920
a_string: Cow<'a, str>,
2021
a_number: u64,
2122
a_timestamp: i64,
@@ -43,20 +44,18 @@ async fn main() -> Result<(), Box<dyn Error>> {
4344
let client = client.with_collection(&collection_name);
4445

4546
for i in 0u64..5 {
46-
let doc = Document::new(
47-
format!("unique_id{}", i),
48-
MySampleStruct {
49-
a_string: Cow::Borrowed("Something here"),
50-
a_number: i,
51-
a_timestamp: chrono::Utc::now().timestamp(),
52-
},
53-
);
47+
let doc = Document::new(MySampleStruct {
48+
id: Cow::Owned(format!("unique_id{}", i)),
49+
a_string: Cow::Borrowed("Something here"),
50+
a_number: i,
51+
a_timestamp: chrono::Utc::now().timestamp(),
52+
});
5453

5554
// let's add an entity.
5655
client
5756
.create_document()
5857
.with_document(&doc)
59-
.with_partition_keys(PartitionKeys::new().push(doc.document_attributes.id())?)
58+
.with_partition_keys(PartitionKeys::new().push(&doc.document.id)?)
6059
.execute()
6160
.await?;
6261
}
@@ -136,6 +135,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
136135
.replace_document()
137136
.with_document(&doc.document)
138137
.with_partition_keys(PartitionKeys::new().push(&id)?)
138+
.with_document_id(&id)
139139
.with_consistency_level(ConsistencyLevel::from(&response))
140140
.with_if_match_condition(IfMatchCondition::Match(&etag)) // use optimistic concurrency check
141141
.execute()

azure_sdk_cosmos/examples/document_entries01.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ extern crate serde_derive;
66

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

35-
let mut doc = Document::new(
36-
format!("unique_id{}", 500),
37-
MySampleStruct {
38-
a_string: Cow::Borrowed("Something here"),
39-
a_number: 600,
40-
a_timestamp: chrono::Utc::now().timestamp(),
41-
},
42-
);
36+
let mut doc = Document::new(MySampleStruct {
37+
id: Cow::Owned(format!("unique_id{}", 500)),
38+
a_string: Cow::Borrowed("Something here"),
39+
a_number: 600,
40+
a_timestamp: chrono::Utc::now().timestamp(),
41+
});
4342

4443
let mut partition_keys = PartitionKeys::new();
45-
partition_keys.push(doc.document_attributes.id())?;
44+
partition_keys.push(&doc.document.id)?;
4645

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

61-
let document_client = client.with_document(&doc, &partition_keys);
60+
let document_client = client.with_document(&doc.document.id, &partition_keys);
6261

6362
let get_document_response = document_client
6463
.get_document()
@@ -99,6 +98,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
9998
let replace_document_response = client
10099
.replace_document()
101100
.with_document(&doc)
101+
.with_document_id(&doc.document.id)
102102
.with_partition_keys(&partition_keys)
103103
.execute()
104104
.await?;

azure_sdk_cosmos/examples/query_document00.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -44,24 +44,25 @@ async fn main() -> Result<(), Box<dyn Error>> {
4444
let client = client.with_collection(&collection_name);
4545

4646
let query_obj = Query::new(&query);
47-
let respo: QueryDocumentsResponse<MySecondSampleStructOwned> = client
47+
48+
let respo: QueryDocumentsResponse<serde_json::Value> = client
4849
.query_documents()
4950
.with_query(&query_obj)
5051
.with_query_cross_partition(true)
51-
.with_parallelize_cross_partition_query(true)
52-
.with_max_item_count(2)
52+
.with_max_item_count(3)
5353
.execute()
5454
.await?;
55-
println!("as items == {:?}", respo);
55+
println!("as json == {:?}", respo);
5656

57-
let respo: QueryDocumentsResponse<serde_json::Value> = client
57+
let respo: QueryDocumentsResponse<MySecondSampleStructOwned> = client
5858
.query_documents()
5959
.with_query(&query_obj)
6060
.with_query_cross_partition(true)
61-
.with_max_item_count(3)
61+
.with_parallelize_cross_partition_query(true)
62+
.with_max_item_count(2)
6263
.execute()
6364
.await?;
64-
println!("as json == {:?}", respo);
65+
println!("as items == {:?}", respo);
6566

6667
//let ret = client
6768
// .query_documents(

0 commit comments

Comments
 (0)