Skip to content

Commit 80a0e6e

Browse files
authored
[Tables] Add select parameter to getEntity methods (Azure#15737)
* Expose select parameter to getEntity method * Fix copy/paste error in updateEntity * Remove unimplemented listEntities(timeout) * Fix updateEntity missing implementation
1 parent 75fdd40 commit 80a0e6e

File tree

5 files changed

+192
-31
lines changed

5 files changed

+192
-31
lines changed

sdk/tables/azure-data-tables/CHANGELOG.md

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,17 @@
22

33
## 12.0.0-beta.2 (Unreleased)
44

5-
### Fixes
5+
### Changed
66

7-
- Can Not Create TableClientBuilder #15294
8-
- Missing module-info.java #15296
7+
- The `getEntity` methods have gained the `select` query option to allow for more efficient existence checks for a table entity [#15289](https://github.com/Azure/azure-sdk-for-java/issues/15289)
8+
9+
### Fixed
10+
11+
- Can Not Create TableClientBuilder [#15294](https://github.com/Azure/azure-sdk-for-java/issues/15294)
12+
- Missing module-info.java [#15296](https://github.com/Azure/azure-sdk-for-java/issues/15296)
13+
- The `TableClient.updateEntity(entity)` method was mistakenly performing an upsert operation rather than an update
14+
- The `TableAsyncClient.updateEntity(entity)` method always returned an empty result
15+
- The non-functional `TableClient.listEntities(options, timeout)` method was removed
916

1017
## 12.0.0-beta.1 (2020-09-10):
1118

sdk/tables/azure-data-tables/src/main/java/com/azure/data/tables/TableAsyncClient.java

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import com.azure.core.http.rest.Response;
1414
import com.azure.core.http.rest.SimpleResponse;
1515
import com.azure.core.util.Context;
16+
import com.azure.core.util.FluxUtil;
1617
import com.azure.core.util.IterableStream;
1718
import com.azure.core.util.logging.ClientLogger;
1819
import com.azure.core.util.serializer.SerializerAdapter;
@@ -51,8 +52,6 @@ public class TableAsyncClient {
5152
private final AzureTableImpl implementation;
5253
private final String accountName;
5354
private final String tableUrl;
54-
private final QueryOptions defaultQueryOptions = new QueryOptions()
55-
.setFormat(OdataMetadataFormat.APPLICATION_JSON_ODATA_FULLMETADATA);
5655

5756
TableAsyncClient(String tableName, AzureTableImpl implementation) {
5857
try {
@@ -247,22 +246,25 @@ Mono<Response<Void>> upsertEntityWithResponse(TableEntity entity, UpdateMode upd
247246
}
248247

249248
/**
250-
* if UpdateMode is MERGE, merges or fails if the entity doesn't exist. If UpdateMode is REPLACE replaces or fails
251-
* if the entity doesn't exist
249+
* updates the entity, using UpdateMode.MERGE
250+
*
251+
* merges or fails if the entity doesn't exist.
252252
*
253253
* @param entity the entity to update
254254
*
255255
* @return void
256256
*/
257257
@ServiceMethod(returns = ReturnType.SINGLE)
258258
public Mono<Void> updateEntity(TableEntity entity) {
259-
//TODO: merge or throw an error if it cannot be found
260-
return Mono.empty();
259+
return updateEntity(entity, null);
261260
}
262261

263262
/**
264263
* updates the entity
265264
*
265+
* if UpdateMode is MERGE, merges or fails if the entity doesn't exist. If UpdateMode is REPLACE replaces or fails
266+
* if the entity doesn't exist
267+
*
266268
* @param entity the entity to update
267269
* @param updateMode which type of mode to execute
268270
*
@@ -274,6 +276,8 @@ public Mono<Void> updateEntity(TableEntity entity, UpdateMode updateMode) {
274276
}
275277

276278
/**
279+
* updates the entity
280+
*
277281
* if UpdateMode is MERGE, merges or fails if the entity doesn't exist. If UpdateMode is REPLACE replaces or fails
278282
* if the entity doesn't exist
279283
*
@@ -290,6 +294,8 @@ public Mono<Void> updateEntity(TableEntity entity, boolean ifUnchanged, UpdateMo
290294
}
291295

292296
/**
297+
* updates the entity
298+
*
293299
* if UpdateMode is MERGE, merges or fails if the entity doesn't exist. If UpdateMode is REPLACE replaces or fails
294300
* if the entity doesn't exist
295301
*
@@ -582,28 +588,50 @@ public void close() {
582588
*/
583589
@ServiceMethod(returns = ReturnType.SINGLE)
584590
public Mono<TableEntity> getEntity(String partitionKey, String rowKey) {
585-
return getEntityWithResponse(partitionKey, rowKey).flatMap(response ->
586-
Mono.justOrEmpty(response.getValue()));
591+
return getEntityWithResponse(partitionKey, rowKey, null).flatMap(FluxUtil::toMono);
592+
}
593+
594+
/**
595+
* gets the entity which fits the given criteria
596+
*
597+
* @param partitionKey the partition key of the entity
598+
* @param rowKey the row key of the entity
599+
* @param select a select expression using OData notation. Limits the columns on each record to just those
600+
* requested, e.g. "$select=PolicyAssignmentId, ResourceId".
601+
*
602+
* @return a mono of the table entity
603+
*/
604+
@ServiceMethod(returns = ReturnType.SINGLE)
605+
public Mono<TableEntity> getEntity(String partitionKey, String rowKey, String select) {
606+
return getEntityWithResponse(partitionKey, rowKey, select).flatMap(FluxUtil::toMono);
587607
}
588608

589609
/**
590610
* gets the entity which fits the given criteria
591611
*
592612
* @param partitionKey the partition key of the entity
593613
* @param rowKey the row key of the entity
614+
* @param select a select expression using OData notation. Limits the columns on each record to just those
615+
* requested, e.g. "$select=PolicyAssignmentId, ResourceId".
594616
*
595617
* @return a mono of the response with the table entity
596618
*/
597619
@ServiceMethod(returns = ReturnType.SINGLE)
598-
public Mono<Response<TableEntity>> getEntityWithResponse(String partitionKey, String rowKey) {
599-
return withContext(context -> getEntityWithResponse(partitionKey, rowKey, defaultQueryOptions, context));
620+
public Mono<Response<TableEntity>> getEntityWithResponse(String partitionKey, String rowKey, String select) {
621+
return withContext(context -> getEntityWithResponse(partitionKey, rowKey, select, null, context));
600622
}
601623

602-
Mono<Response<TableEntity>> getEntityWithResponse(String partitionKey, String rowKey, QueryOptions queryOptions,
603-
Context context) {
624+
Mono<Response<TableEntity>> getEntityWithResponse(String partitionKey, String rowKey, String select,
625+
Duration timeout, Context context) {
626+
Integer timeoutInt = timeout == null ? null : (int) timeout.getSeconds();
627+
QueryOptions queryOptions = new QueryOptions()
628+
.setFormat(OdataMetadataFormat.APPLICATION_JSON_ODATA_FULLMETADATA);
629+
if (select != null) {
630+
queryOptions.setSelect(select);
631+
}
604632

605633
return implementation.getTables().queryEntitiesWithPartitionAndRowKeyWithResponseAsync(tableName, partitionKey,
606-
rowKey, null, null, queryOptions, context)
634+
rowKey, timeoutInt, null, queryOptions, context)
607635
.handle((response, sink) -> {
608636
final TableEntityQueryResponse entityQueryResponse = response.getValue();
609637
if (entityQueryResponse == null) {

sdk/tables/azure-data-tables/src/main/java/com/azure/data/tables/TableClient.java

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
import com.azure.core.http.rest.PagedIterable;
99
import com.azure.core.http.rest.Response;
1010
import com.azure.core.util.Context;
11-
import com.azure.data.tables.implementation.models.QueryOptions;
1211
import com.azure.data.tables.models.ListEntitiesOptions;
1312
import com.azure.data.tables.models.TableEntity;
1413
import com.azure.data.tables.models.UpdateMode;
@@ -185,7 +184,7 @@ public Response<Void> upsertEntityWithResponse(TableEntity entity, UpdateMode up
185184
*/
186185
@ServiceMethod(returns = ReturnType.SINGLE)
187186
public void updateEntity(TableEntity entity) {
188-
client.upsertEntity(entity).block();
187+
client.updateEntity(entity).block();
189188
}
190189

191190
/**
@@ -348,40 +347,61 @@ public PagedIterable<TableEntity> listEntities(ListEntitiesOptions options) {
348347
}
349348

350349
/**
351-
* Queries and returns entities in the given table using the odata QueryOptions
350+
* gets the entity which fits the given criteria
352351
*
353-
* @param options the odata query object
354-
* @param timeout max time for query to execute before erroring out
355-
* @return a list of the tables that fit the query
352+
* @param partitionKey the partition key of the entity
353+
* @param rowKey the row key of the entity
354+
* @return the table entity
356355
*/
357-
@ServiceMethod(returns = ReturnType.COLLECTION)
358-
public PagedIterable<TableEntity> listEntities(ListEntitiesOptions options, Duration timeout) {
359-
return null;
356+
@ServiceMethod(returns = ReturnType.SINGLE)
357+
public TableEntity getEntity(String partitionKey, String rowKey) {
358+
return client.getEntity(partitionKey, rowKey).block();
360359
}
361360

362361
/**
363362
* gets the entity which fits the given criteria
364363
*
365364
* @param partitionKey the partition key of the entity
366365
* @param rowKey the row key of the entity
366+
* @param select a select expression using OData notation. Limits the columns on each record to just those
367+
* requested, e.g. "$select=PolicyAssignmentId, ResourceId".
367368
* @return the table entity
368369
*/
369370
@ServiceMethod(returns = ReturnType.SINGLE)
370-
public TableEntity getEntity(String partitionKey, String rowKey) {
371-
return client.getEntity(partitionKey, rowKey).block();
371+
public TableEntity getEntity(String partitionKey, String rowKey, String select) {
372+
return client.getEntity(partitionKey, rowKey, select).block();
372373
}
373374

374375
/**
375376
* gets the entity which fits the given criteria
376377
*
377378
* @param partitionKey the partition key of the entity
378379
* @param rowKey the row key of the entity
380+
* @param select a select expression using OData notation. Limits the columns on each record to just those
381+
* requested, e.g. "$select=PolicyAssignmentId, ResourceId".
382+
* @param timeout max time for query to execute before erroring out
383+
* @return the table entity
384+
*/
385+
@ServiceMethod(returns = ReturnType.SINGLE)
386+
public TableEntity getEntity(String partitionKey, String rowKey, String select, Duration timeout) {
387+
return getEntityWithResponse(partitionKey, rowKey, select, timeout, null).getValue();
388+
}
389+
390+
/**
391+
* gets the entity which fits the given criteria
392+
*
393+
* @param partitionKey the partition key of the entity
394+
* @param rowKey the row key of the entity
395+
* @param select a select expression using OData notation. Limits the columns on each record to just those
396+
* requested, e.g. "$select=PolicyAssignmentId, ResourceId".
397+
* @param timeout max time for query to execute before erroring out
379398
* @param context the context of the query
380399
* @return a mono of the response with the table entity
381400
*/
382401
@ServiceMethod(returns = ReturnType.SINGLE)
383-
public Response<TableEntity> getEntityWithResponse(String partitionKey, String rowKey, Context context) {
384-
return client.getEntityWithResponse(partitionKey, rowKey, new QueryOptions(), context).block();
402+
public Response<TableEntity> getEntityWithResponse(String partitionKey, String rowKey, String select,
403+
Duration timeout, Context context) {
404+
return client.getEntityWithResponse(partitionKey, rowKey, select, timeout, context).block();
385405
}
386406

387407
}

sdk/tables/azure-data-tables/src/test/java/com/azure/data/tables/TablesAsyncClientTest.java

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ void createEntityWithAllSupportedDataTypesAsync() {
198198
tableClient.createEntity(tableEntity).block(TIMEOUT);
199199

200200
// Act & Assert
201-
StepVerifier.create(tableClient.getEntityWithResponse(partitionKeyValue, rowKeyValue))
201+
StepVerifier.create(tableClient.getEntityWithResponse(partitionKeyValue, rowKeyValue, null))
202202
.assertNext(response -> {
203203
final TableEntity entity = response.getValue();
204204
Map<String, Object> properties = entity.getProperties();
@@ -311,7 +311,7 @@ void getEntityWithResponseAsync() {
311311
tableClient.createEntity(tableEntity).block(TIMEOUT);
312312

313313
// Act & Assert
314-
StepVerifier.create(tableClient.getEntityWithResponse(partitionKeyValue, rowKeyValue))
314+
StepVerifier.create(tableClient.getEntityWithResponse(partitionKeyValue, rowKeyValue, null))
315315
.assertNext(response -> {
316316
final TableEntity entity = response.getValue();
317317
assertEquals(expectedStatusCode, response.getStatusCode());
@@ -328,6 +328,33 @@ void getEntityWithResponseAsync() {
328328
.verify();
329329
}
330330

331+
@Test
332+
void getEntityWithResponseWithSelectAsync() {
333+
// Arrange
334+
final String partitionKeyValue = testResourceNamer.randomName("partitionKey", 20);
335+
final String rowKeyValue = testResourceNamer.randomName("rowKey", 20);
336+
final TableEntity tableEntity = new TableEntity(partitionKeyValue, rowKeyValue);
337+
tableEntity.addProperty("Test", "Value");
338+
final int expectedStatusCode = 200;
339+
tableClient.createEntity(tableEntity).block(TIMEOUT);
340+
341+
// Act & Assert
342+
StepVerifier.create(tableClient.getEntityWithResponse(partitionKeyValue, rowKeyValue, "Test"))
343+
.assertNext(response -> {
344+
final TableEntity entity = response.getValue();
345+
assertEquals(expectedStatusCode, response.getStatusCode());
346+
347+
assertNotNull(entity);
348+
assertNull(entity.getPartitionKey());
349+
assertNull(entity.getRowKey());
350+
assertNull(entity.getTimestamp());
351+
assertNotNull(entity.getETag());
352+
assertEquals(entity.getProperties().get("Test"), "Value");
353+
})
354+
.expectComplete()
355+
.verify();
356+
}
357+
331358
@Test
332359
void updateEntityWithResponseReplaceAsync() {
333360
updateEntityWithResponseAsync(UpdateMode.REPLACE);
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
{
2+
"networkCallRecords" : [ {
3+
"Method" : "POST",
4+
"Uri" : "https://REDACTED.table.core.windows.net/Tables",
5+
"Headers" : {
6+
"x-ms-version" : "2019-02-02",
7+
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.8; Mac OS X; 10.15.6)",
8+
"x-ms-client-request-id" : "9c201029-bea7-4cf6-adfa-c6a4485cfbe8",
9+
"Content-Type" : "application/json"
10+
},
11+
"Response" : {
12+
"x-ms-version" : "2019-02-02",
13+
"Server" : "Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0",
14+
"X-Content-Type-Options" : "nosniff",
15+
"retry-after" : "0",
16+
"StatusCode" : "204",
17+
"Date" : "Fri, 25 Sep 2020 23:00:43 GMT",
18+
"Cache-Control" : "no-cache",
19+
"DataServiceId" : "https://brsiegelsample.table.core.windows.net/Tables('tablename39296115')",
20+
"Content-Length" : "0",
21+
"x-ms-request-id" : "d423598b-d002-00da-498f-9353bd000000",
22+
"Preference-Applied" : "return-no-content",
23+
"x-ms-client-request-id" : "9c201029-bea7-4cf6-adfa-c6a4485cfbe8",
24+
"Location" : "https://brsiegelsample.table.core.windows.net/Tables('tablename39296115')"
25+
},
26+
"Exception" : null
27+
}, {
28+
"Method" : "POST",
29+
"Uri" : "https://REDACTED.table.core.windows.net/tablename39296115",
30+
"Headers" : {
31+
"x-ms-version" : "2019-02-02",
32+
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.8; Mac OS X; 10.15.6)",
33+
"x-ms-client-request-id" : "b806fc23-b91d-47ba-9cb8-969acd0164a4",
34+
"Content-Type" : "application/json"
35+
},
36+
"Response" : {
37+
"x-ms-version" : "2019-02-02",
38+
"Server" : "Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0",
39+
"X-Content-Type-Options" : "nosniff",
40+
"retry-after" : "0",
41+
"StatusCode" : "204",
42+
"Date" : "Fri, 25 Sep 2020 23:00:43 GMT",
43+
"Cache-Control" : "no-cache",
44+
"ETag" : "W/datetime'2020-09-25T23%3A00%3A44.0581906Z'",
45+
"DataServiceId" : "https://brsiegelsample.table.core.windows.net/tablename39296115(PartitionKey='partitionkey45611a',RowKey='rowkey880640e72')",
46+
"Content-Length" : "0",
47+
"x-ms-request-id" : "d4235999-d002-00da-548f-9353bd000000",
48+
"Preference-Applied" : "return-no-content",
49+
"x-ms-client-request-id" : "b806fc23-b91d-47ba-9cb8-969acd0164a4",
50+
"Location" : "https://brsiegelsample.table.core.windows.net/tablename39296115(PartitionKey='partitionkey45611a',RowKey='rowkey880640e72')"
51+
},
52+
"Exception" : null
53+
}, {
54+
"Method" : "GET",
55+
"Uri" : "https://REDACTED.table.core.windows.net/tablename39296115(PartitionKey='partitionkey45611a',RowKey='rowkey880640e72')?$format=application/json%3Bodata%3Dfullmetadata&$select=Test",
56+
"Headers" : {
57+
"x-ms-version" : "2019-02-02",
58+
"User-Agent" : "azsdk-java-UnknownName/UnknownVersion (11.0.8; Mac OS X; 10.15.6)",
59+
"x-ms-client-request-id" : "9de688e0-a87c-4d45-979c-df7062536191"
60+
},
61+
"Response" : {
62+
"Transfer-Encoding" : "chunked",
63+
"x-ms-version" : "2019-02-02",
64+
"Server" : "Windows-Azure-Table/1.0 Microsoft-HTTPAPI/2.0",
65+
"X-Content-Type-Options" : "nosniff",
66+
"retry-after" : "0",
67+
"StatusCode" : "200",
68+
"Date" : "Fri, 25 Sep 2020 23:00:43 GMT",
69+
"Cache-Control" : "no-cache",
70+
"ETag" : "W/datetime'2020-09-25T23%3A00%3A44.0581906Z'",
71+
"x-ms-request-id" : "d42359a9-d002-00da-608f-9353bd000000",
72+
"Body" : "{\"odata.metadata\":\"https://brsiegelsample.table.core.windows.net/$metadata#tablename39296115/@Element&$select=Test\",\"odata.type\":\"brsiegelsample.tablename39296115\",\"odata.id\":\"https://brsiegelsample.table.core.windows.net/tablename39296115(PartitionKey='partitionkey45611a',RowKey='rowkey880640e72')\",\"odata.etag\":\"W/\\\"datetime'2020-09-25T23%3A00%3A44.0581906Z'\\\"\",\"odata.editLink\":\"tablename39296115(PartitionKey='partitionkey45611a',RowKey='rowkey880640e72')\",\"Test\":\"Value\"}",
73+
"x-ms-client-request-id" : "9de688e0-a87c-4d45-979c-df7062536191",
74+
"Content-Type" : "application/json;odata=fullmetadata;streaming=true;charset=utf-8"
75+
},
76+
"Exception" : null
77+
} ],
78+
"variables" : [ "tablename39296115", "partitionkey45611a", "rowkey880640e72" ]
79+
}

0 commit comments

Comments
 (0)