Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Regression prevent using update to remove an entry from a map [DATACASS-841] #1007

Closed
spring-projects-issues opened this issue Dec 31, 2020 · 4 comments
Assignees
Labels
type: regression A regression from a previous release

Comments

@spring-projects-issues
Copy link

Luc Boutier opened DATACASS-841 and commented

When migrating a project from 2.x to 3.x I encountered an issue on map field remove operation in a map.

@Table("contact")
class Contact(
    @PrimaryKeyColumn(name = "account_key", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
    var accountKey: UUID,
    @PrimaryKeyColumn(name = "id", ordinal = 1, type = PrimaryKeyType.PARTITIONED)
    var id: UUID,
    @Column("entity_details")
    var entityDetails: MutableMap<UUID, ContactEntityDetails> = mutableMapOf()
)

// Later in some update method:
val update = Update.RemoveOp(ColumnName.from("entityDetails"), entityId)
val query = Query.query(
    Criteria.where("accountKey").`is`(accountKey),
    Criteria.where("id").`is`(id)
)
return cassandraTemplate.update(query, update, Contact::class.java)

 

The update statement generated is the following:

UPDATE contact SET entity_details=entity_details-00000000-0000-4000-9000-000000000002 WHERE account_key=f9b520c9-c928-4360-ae69-90d4373cbd57 AND id=6dd405dc-cfbb-40ec-a626-ec18df63ab6d

There is curly braces missing as stated here 

 And this should be if I'm correct

UPDATE contact SET entity_details=entity_details-{00000000-0000-4000-9000-000000000002} WHERE account_key=f9b520c9-c928-4360-ae69-90d4373cbd57 AND id=6dd405dc-cfbb-40ec-a626-ec18df63ab6d

 

 


Affects: 3.1.2 (2020.0.2)

@spring-projects-issues spring-projects-issues added the type: bug A general bug label Dec 31, 2020
@mp911de mp911de changed the title Regression prevent using update to remove an entry from a map. [DATACASS-841] Regression prevent using update to remove an entry from a map [DATACASS-841] Jan 29, 2021
@mp911de mp911de added type: enhancement A general enhancement type: regression A regression from a previous release and removed type: bug A general bug labels Jan 29, 2021
@mp911de
Copy link
Member

mp911de commented Jan 29, 2021

Hey @lucboutier, there are a couple of issues here. We didn't expose remove from map as we missed that one. Map value removal is limited to a single element only because the DataStax QueryBuilder API. Let's see whether we can navigate around that limitation.

Deleting map entries works only by specifying the value, not the key. For whatever reason, CQL requires a DELETE statement to remove a map entry by key.

@mp911de
Copy link
Member

mp911de commented Jan 29, 2021

That's interesting. entity_details=entity_details-{'hello'} removes the entry by key, not by value. What's a bit strange is that Assignment.removeMapEntry(…) expects a key and a value (both non-null) and the implementation checks only if the key is non-null which can easily lead to the assumption that map removals happen by value.

The docs meanwhile aren't fully clear and a bit confusing:

Alternatively, remove all elements having a particular value using the UPDATE command, the subtraction operator (-), and the map key values in curly brackets.

It should be:

Alternatively, remove all elements having a particular key using the UPDATE command, the subtraction operator (-), and the map key values in curly brackets.

/cc @adutra

@mp911de
Copy link
Member

mp911de commented Jan 29, 2021

This change requires quite some changes, so backporting it only to 3.1.x and master.

@mp911de mp911de removed the type: enhancement A general enhancement label Jan 29, 2021
mp911de added a commit that referenced this issue Jan 29, 2021
We now accept multiple values when removing items from a collection. Additionally, we support now removal by key/keys for map columns.

Resolves #1007.
@lucboutier
Copy link

Indeed I got confused by our workaround implementation and past behavior when reading your initial comment and actual documentation again.. That's indeed weird..

Note that our current workaround is to use a prepared statement that we create through the following:

         stmtCache, QueryBuilder.update("contact")
             .remove("entity_details", QueryBuilder.bindMarker("entity_id"))
             .whereColumn("account_key").isEqualTo(QueryBuilder.bindMarker("account_key"))
             .whereColumn("id").isEqualTo(QueryBuilder.bindMarker("id"))
             .ifExists()
             .build()
     ).createPreparedStatement(session)```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: regression A regression from a previous release
Projects
None yet
Development

No branches or pull requests

3 participants