@@ -291,7 +291,7 @@ Mono<Response<TableItem>> createTableWithResponse(Context context) {
291291
292292 try {
293293 return tablesImplementation .getTables ().createWithResponseAsync (properties , null ,
294- ResponseFormat .RETURN_NO_CONTENT , null , context )
294+ ResponseFormat .RETURN_NO_CONTENT , null , context )
295295 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
296296 .map (response ->
297297 new SimpleResponse <>(response ,
@@ -441,7 +441,7 @@ Mono<Response<Void>> createEntityWithResponse(TableEntity entity, Context contex
441441
442442 try {
443443 return tablesImplementation .getTables ().insertEntityWithResponseAsync (tableName , null , null ,
444- ResponseFormat .RETURN_NO_CONTENT , entity .getProperties (), null , context )
444+ ResponseFormat .RETURN_NO_CONTENT , entity .getProperties (), null , context )
445445 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
446446 .map (response ->
447447 new SimpleResponse <>(response .getRequest (), response .getStatusCode (), response .getHeaders (), null ));
@@ -537,21 +537,24 @@ Mono<Response<Void>> upsertEntityWithResponse(TableEntity entity, TableEntityUpd
537537 return monoError (logger , new IllegalArgumentException ("'entity' cannot be null." ));
538538 }
539539
540+ String partitionKey = escapeSingleQuotes (entity .getPartitionKey ());
541+ String rowKey = escapeSingleQuotes (entity .getRowKey ());
542+
540543 EntityHelper .setPropertiesFromGetters (entity , logger );
541544
542545 try {
543546 if (updateMode == TableEntityUpdateMode .REPLACE ) {
544547 return tablesImplementation .getTables ()
545- .updateEntityWithResponseAsync (tableName , entity . getPartitionKey (), entity . getRowKey () , null ,
546- null , null , entity .getProperties (), null , context )
548+ .updateEntityWithResponseAsync (tableName , partitionKey , rowKey , null , null , null ,
549+ entity .getProperties (), null , context )
547550 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
548551 .map (response ->
549552 new SimpleResponse <>(response .getRequest (), response .getStatusCode (), response .getHeaders (),
550553 null ));
551554 } else {
552555 return tablesImplementation .getTables ()
553- .mergeEntityWithResponseAsync (tableName , entity . getPartitionKey (), entity . getRowKey () , null , null ,
554- null , entity .getProperties (), null , context )
556+ .mergeEntityWithResponseAsync (tableName , partitionKey , rowKey , null , null , null ,
557+ entity .getProperties (), null , context )
555558 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
556559 .map (response ->
557560 new SimpleResponse <>(response .getRequest (), response .getStatusCode (), response .getHeaders (),
@@ -649,7 +652,8 @@ public Mono<Void> updateEntity(TableEntity entity, TableEntityUpdateMode updateM
649652 * <p>When the {@link TableEntityUpdateMode update mode} is {@link TableEntityUpdateMode#MERGE MERGE}, the provided
650653 * {@link TableEntity entity}'s properties will be merged into the existing {@link TableEntity entity}. When the
651654 * {@link TableEntityUpdateMode update mode} is {@link TableEntityUpdateMode#REPLACE REPLACE}, the provided
652- * {@link TableEntity entity}'s properties will completely replace those in the existing {@link TableEntity entity}.
655+ * {@link TableEntity entity}'s properties will completely replace those in the existing
656+ * {@link TableEntity entity}.
653657 * </p>
654658 *
655659 * <p><strong>Code Samples</strong></p>
@@ -700,22 +704,25 @@ Mono<Response<Void>> updateEntityWithResponse(TableEntity entity, TableEntityUpd
700704 return monoError (logger , new IllegalArgumentException ("'entity' cannot be null." ));
701705 }
702706
707+ String partitionKey = escapeSingleQuotes (entity .getPartitionKey ());
708+ String rowKey = escapeSingleQuotes (entity .getRowKey ());
703709 String eTag = ifUnchanged ? entity .getETag () : "*" ;
710+
704711 EntityHelper .setPropertiesFromGetters (entity , logger );
705712
706713 try {
707714 if (updateMode == TableEntityUpdateMode .REPLACE ) {
708715 return tablesImplementation .getTables ()
709- .updateEntityWithResponseAsync (tableName , entity . getPartitionKey (), entity . getRowKey () , null ,
710- null , eTag , entity .getProperties (), null , context )
716+ .updateEntityWithResponseAsync (tableName , partitionKey , rowKey , null , null , eTag ,
717+ entity .getProperties (), null , context )
711718 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
712719 .map (response ->
713720 new SimpleResponse <>(response .getRequest (), response .getStatusCode (), response .getHeaders (),
714721 null ));
715722 } else {
716723 return tablesImplementation .getTables ()
717- .mergeEntityWithResponseAsync (tableName , entity . getPartitionKey (), entity . getRowKey () , null , null ,
718- eTag , entity .getProperties (), null , context )
724+ .mergeEntityWithResponseAsync (tableName , partitionKey , rowKey , null , null , eTag ,
725+ entity .getProperties (), null , context )
719726 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
720727 .map (response ->
721728 new SimpleResponse <>(response .getRequest (), response .getStatusCode (), response .getHeaders (),
@@ -839,8 +846,8 @@ Mono<Response<Void>> deleteEntityWithResponse(String partitionKey, String rowKey
839846 }
840847
841848 try {
842- return tablesImplementation .getTables ().deleteEntityWithResponseAsync (tableName , partitionKey , rowKey , eTag ,
843- null , null , null , context )
849+ return tablesImplementation .getTables ().deleteEntityWithResponseAsync (tableName ,
850+ escapeSingleQuotes ( partitionKey ), escapeSingleQuotes ( rowKey ), eTag , null , null , null , context )
844851 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
845852 .map (response -> (Response <Void >) new SimpleResponse <Void >(response , null ))
846853 .onErrorResume (TableServiceException .class , e -> swallowExceptionForStatusCode (404 , e , logger ));
@@ -974,7 +981,7 @@ private <T extends TableEntity> Mono<PagedResponse<T>> listEntities(String nextP
974981
975982 try {
976983 return tablesImplementation .getTables ().queryEntitiesWithResponseAsync (tableName , null , null ,
977- nextPartitionKey , nextRowKey , queryOptions , context )
984+ nextPartitionKey , nextRowKey , queryOptions , context )
978985 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
979986 .flatMap (response -> {
980987 final TableEntityQueryResponse tablesQueryEntityResponse = response .getValue ();
@@ -1148,7 +1155,7 @@ <T extends TableEntity> Mono<Response<T>> getEntityWithResponse(String partition
11481155
11491156 try {
11501157 return tablesImplementation .getTables ().queryEntityWithPartitionAndRowKeyWithResponseAsync (tableName ,
1151- partitionKey , rowKey , null , null , queryOptions , context )
1158+ escapeSingleQuotes ( partitionKey ), escapeSingleQuotes ( rowKey ) , null , null , queryOptions , context )
11521159 .onErrorMap (TableUtils ::mapThrowableToTableServiceException )
11531160 .handle ((response , sink ) -> {
11541161 final Map <String , Object > matchingEntity = response .getValue ();
@@ -1742,4 +1749,14 @@ private Mono<Response<List<TableTransactionActionResponse>>> parseResponse(Trans
17421749 return Mono .just (new SimpleResponse <>(response , Arrays .asList (response .getValue ())));
17431750 }
17441751 }
1752+
1753+ // Single quotes in OData queries should be escaped by using two consecutive single quotes characters.
1754+ // Source: http://docs.oasis-open.org/odata/odata/v4.01/odata-v4.01-part2-url-conventions.html#sec_URLSyntax.
1755+ private String escapeSingleQuotes (String input ) {
1756+ if (input == null ) {
1757+ return null ;
1758+ }
1759+
1760+ return input .replace ("'" , "''" );
1761+ }
17451762}
0 commit comments