[DATACASS-546] Unable to delete user-defined types when one UDT references another Created: 13/Apr/18  Updated: 08/May/18  Resolved: 23/Apr/18

Status: Closed
Project: Spring Data for Apache Cassandra
Component/s: None
Affects Version/s: None
Fix Version/s: 1.5.12 (Ingalls SR12), 2.0.7 (Kay SR7), 2.1 M3 (Lovelace)

Type: Bug Priority: Major
Reporter: Craig Walls Assignee: Mark Paluch
Resolution: Fixed Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Days since last comment: 1 year, 31 weeks, 4 days ago
Last commented by a User: true
Last updater: Mark Paluch
Sprint: Lovelace M2 / M3

 Description   

SD-Cassandra is not considering user-defined types that are referenced by other user-defined types when dropping/recreating schemas. This results in an error and failure for the application to restart.

tl;dr
If SD-Cassandra is configured to drop/recreate a schema upon application restart, it is important that user-defined types (UDT) are dropped in an order that accounts for references to other UDTs. If not, then a drop type will fail, resulting in the application failing to start. When working in developer mode (which is when you'd typically drop/recreate schemas frequently), this renders Spring Boot DevTools useless, because you would need to manually delete the UDTs before manually restarting the application.

For example, suppose that you have defined two UDTs, "pizza" and "toppings", such that "pizza" references "toppings". It is important that the "pizza" UDT be dropped before the "toppings" UDT or else you'll get an error that looks like this:

InvalidRequest: Error from server: code=2200 [Invalid query] message="Cannot drop user type pizzaapp.topping as it is still used by table pizzaapp.pizza"

A look at https://github.com/spring-projects/spring-data-cassandra/blob/master/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraPersistentEntitySchemaDropper.java#L83-L98 doesn't reveal anything obvious about the ordering of how UDTs are dropped. But neither does the dropTables() method above it--and I am assuming that dropTables() considers tables that reference each other when it is dropping them. (Or at least, I've not encountered any problems with tables like I'm having with UDTs.)

Side note: dropUserTypes() is quite similar in function to dropTables(), but they are written quite differently. One uses streams, while the other iterates over a collection. It would be nice if those two methods were more consistent in their coding (I favor the streams style).



 Comments   
Comment by Mark Paluch [ 16/Apr/18 ]

Schema dropper does not consider dependencies between user-defined types. Cassandra does not have a notion of foreign keys (or any other type of dependencies between tables), so dropping tables in any order is always safe. For UDT's we need to walk the dependency graph. We already consider dependencies for creation in CassandraPersistentEntitySchemaCreator so we need to apply a similar pattern in deletion and reverse the determined order.

Comment by Mark Paluch [ 16/Apr/18 ]

I pushed a fixed version to the ticket branch. Care to use 2.1.0.DATACASS-546-SNAPSHOT to pull the snapshot artifacts in your build and verify the fix?

Comment by Craig Walls [ 16/Apr/18 ]

Yes! This seems to do the trick. Just to give some info on what I did to test this:

  • Added the Spring Data Cassandra snapshot mentioned above
  • Changed the Spring Data Release Train to Lovelace-BUILD-SNAPSHOT
  • Started the application, which built the tables and UDTs initially
  • Restarted the application, which dropped everything and rebuilt the tables and UDTs

It was that last step that was giving me trouble previously. With the new snapshot it is working perfectly. Thanks!

Generated at Sat Nov 23 02:14:01 UTC 2019 using Jira 7.13.8#713008-sha1:1606a5c1e7006e1ab135aac81f7a9566b2dbc3a6.