Skip to content

Commit 4bce3a3

Browse files
feat: Add support for getting a specific entity from table storage (Azure#226)
* feat: Add support for getting a specific entity from table storage * style: Remove unused imports * fix: Correctly deserialize the response for a single entity get * style: Run cargo fmt
1 parent d52bbf6 commit 4bce3a3

File tree

6 files changed

+122
-4
lines changed

6 files changed

+122
-4
lines changed

sdk/storage/examples/table_00.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,10 +78,12 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
7878
let response = table.insert().return_entity(false).execute(&entity).await?;
7979
println!("response = {:?}\n", response);
8080

81-
let mut entity = MyEntity {
82-
city: "Rome".to_owned(),
83-
..entity
84-
};
81+
// Get an entity from the table
82+
let response = entity_client.get().execute().await?;
83+
println!("response = {:?}\n", response);
84+
85+
let mut entity: MyEntity = response.entity;
86+
entity.city = "Rome".to_owned();
8587

8688
let response = table.insert().return_entity(true).execute(&entity).await?;
8789
println!("response = {:?}\n", response);

sdk/storage/src/table/clients/entity_client.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ impl EntityClient {
5151
&self.row_key
5252
}
5353

54+
pub fn get(&self) -> GetEntityBuilder {
55+
GetEntityBuilder::new(self)
56+
}
57+
5458
pub fn update(&self) -> UpdateOrMergeEntityBuilder {
5559
UpdateOrMergeEntityBuilder::new(self, update_or_merge_entity_builder::Operation::Update)
5660
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
use crate::table::prelude::*;
2+
use crate::table::responses::*;
3+
use azure_core::prelude::*;
4+
use azure_core::{headers::add_optional_header, AppendToUrlQuery};
5+
use http::method::Method;
6+
use http::status::StatusCode;
7+
use serde::de::DeserializeOwned;
8+
use std::convert::TryInto;
9+
10+
#[derive(Debug, Clone)]
11+
pub struct GetEntityBuilder<'a> {
12+
entity_client: &'a EntityClient,
13+
select: Option<Select<'a>>,
14+
client_request_id: Option<ClientRequestId<'a>>,
15+
}
16+
17+
impl<'a> GetEntityBuilder<'a> {
18+
pub(crate) fn new(entity_client: &'a EntityClient) -> Self {
19+
Self {
20+
entity_client,
21+
select: None,
22+
client_request_id: None,
23+
}
24+
}
25+
26+
setters! {
27+
select: Select<'a> => Some(select),
28+
client_request_id: ClientRequestId<'a> => Some(client_request_id),
29+
}
30+
31+
pub async fn execute<E>(
32+
&self,
33+
) -> Result<GetEntityResponse<E>, Box<dyn std::error::Error + Sync + Send>>
34+
where
35+
E: DeserializeOwned,
36+
{
37+
let mut url = self.entity_client.url().to_owned();
38+
39+
self.select.append_to_url_query(&mut url);
40+
41+
debug!("list tables url = {}", url);
42+
43+
let request = self.entity_client.prepare_request(
44+
url.as_str(),
45+
&Method::GET,
46+
&|mut request| {
47+
request = add_optional_header(&self.client_request_id, request);
48+
request = request.header("Accept", "application/json;odata=fullmetadata");
49+
request
50+
},
51+
None,
52+
)?;
53+
54+
debug!("request == {:#?}\n", request);
55+
56+
let response = self
57+
.entity_client
58+
.http_client()
59+
.execute_request_check_status(request.0, StatusCode::OK)
60+
.await?;
61+
62+
Ok((&response).try_into()?)
63+
}
64+
}

sdk/storage/src/table/requests/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
mod create_table_builder;
22
mod delete_entity_builder;
33
mod delete_table_builder;
4+
mod get_entity_builder;
45
mod insert_entity_builder;
56
pub(crate) mod insert_or_replace_or_merge_entity_builder;
67
mod list_tables_builder;
@@ -9,6 +10,7 @@ pub(crate) mod update_or_merge_entity_builder;
910
pub use create_table_builder::CreateTableBuilder;
1011
pub use delete_entity_builder::DeleteEntityBuilder;
1112
pub use delete_table_builder::DeleteTableBuilder;
13+
pub use get_entity_builder::GetEntityBuilder;
1214
pub use insert_entity_builder::InsertEntityBuilder;
1315
pub use insert_or_replace_or_merge_entity_builder::InsertOrReplaceOrMergeEntityBuilder;
1416
pub use list_tables_builder::ListTablesBuilder;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use azure_core::{errors::AzureError, headers::CommonStorageResponseHeaders};
2+
use bytes::Bytes;
3+
use http::Response;
4+
use serde::de::DeserializeOwned;
5+
use std::convert::{TryFrom, TryInto};
6+
7+
#[derive(Debug, Clone)]
8+
pub struct GetEntityResponse<E>
9+
where
10+
E: DeserializeOwned,
11+
{
12+
pub common_storage_response_headers: CommonStorageResponseHeaders,
13+
pub metadata: String,
14+
pub entity: E,
15+
}
16+
17+
#[derive(Debug, Clone, Deserialize, Serialize)]
18+
struct GetEntityResponseInternal<E> {
19+
#[serde(rename = "odata.metadata")]
20+
pub metadata: String,
21+
#[serde(flatten)]
22+
pub value: E,
23+
}
24+
25+
impl<E> TryFrom<&Response<Bytes>> for GetEntityResponse<E>
26+
where
27+
E: DeserializeOwned,
28+
{
29+
type Error = AzureError;
30+
31+
fn try_from(response: &Response<Bytes>) -> Result<Self, Self::Error> {
32+
debug!("{}", std::str::from_utf8(response.body())?);
33+
debug!("headers == {:#?}", response.headers());
34+
35+
let get_entity_response_internal: GetEntityResponseInternal<E> =
36+
serde_json::from_slice(response.body())?;
37+
38+
Ok(GetEntityResponse {
39+
common_storage_response_headers: response.headers().try_into()?,
40+
metadata: get_entity_response_internal.metadata,
41+
entity: get_entity_response_internal.value,
42+
})
43+
}
44+
}

sdk/storage/src/table/responses/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
mod create_table_response;
22
mod delete_entity_response;
33
mod delete_table_response;
4+
mod get_entity_response;
45
mod insert_entity_response;
56
mod list_tables_response;
67
mod operation_on_entity_response;
78
mod submit_transaction_response;
89
pub use create_table_response::CreateTableResponse;
910
pub use delete_entity_response::DeleteEntityResponse;
1011
pub use delete_table_response::DeleteTableResponse;
12+
pub use get_entity_response::GetEntityResponse;
1113
pub use insert_entity_response::InsertEntityResponse;
1214
pub use list_tables_response::ListTablesResponse;
1315
pub use operation_on_entity_response::OperationOnEntityResponse;

0 commit comments

Comments
 (0)