-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
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
onDelete cascade for paranoid tables #2586
Comments
You need the opposite relationship aswell, |
Thanks for the fast reply. I tried with the opposite relationship as well but it didn't work. =( Is the code above with the opposite relationship working on your machine? |
Did you force sync? |
I was deleting the db myself. But now I just set the option force to true but it is still not working. Here is the updated code: var Sequelize = require('sequelize')
, sequelize = new Sequelize('advo_test', 'advo', 'preveza', {dialect: 'postgres'});
var User = sequelize.define('User', {
username: Sequelize.STRING,
birthday: Sequelize.DATE
}, {paranoid: true}); //Without paranoid the code works fine
var Email = sequelize.define('Email', {
email: Sequelize.STRING,
primary: Sequelize.BOOLEAN
}, {paranoid: true}); //Without paranoid the code works fine
User.hasMany(Email, {onDelete: 'cascade'});
Email.belongsTo(User, {onDelete: 'cascade'});
sequelize.sync({force:true}).success(function () {
..... REST OF THE CODE OMITTED ...... |
I completely missed the paranoid part. Edit: The |
Ahh. =/ Is cascade for paranoid tables a feature that you guys are planning on adding on other versions of sequelize? I was reading some older issues and I found this one: #2404 And I saw there was a patch to make it work on sequelize 1.7. So my question is, did you guys remove the cascade for paranoid tables on version 2.0.0? Is there a reason for that? Thanks again for the fast reply. =) |
That issue doesn't really have anything to do with your issue here. |
True. I thought that it had but that was just related to the transaction. Thanks again. That feature is probably something we are going to work on here. I will post a PR later if we find a good generic solution for it. PS.: I noticed that I created a reference between this issue with the issue related to the transaction not been passed on the option hash for paranoid tables. Should I remove the reference by updating my comment? Or there is a better way to remove the reference? |
Any updates on this? It is planned to be included in v4? |
@diosney if it was, it would have the v4 milestone 😉 |
Jajaja! You made my day 😄 That was an indirect? If so I'm willingly to do it with the correct guidance 😉 |
Almost all of Sequelize features come from user contributions 😉 |
@lao what solution did you eventually come up with? I need the same functionality on an app I'm building, so I'm just using managed transactions to do this. |
+1for the feature |
@ajmueller unfortunately we didn't work on a generic solution. I think we ended up using managed transactions as well. But I am not sure. It was a few years ago and I don't work on the project anymore. =/ |
@lao thanks for the reply. I actually ended up changing to not use the paranoid feature for deletes. Instead I built a common interface whereby users must manually type "DELETE" into a text input in a modal if they want to delete something. |
Anyone made any progress on this? Considering spending some time on it but not 100% sure where to start. |
Hello! |
Would be nice if the docs would indicate that the onDelete needs to be in the table creation. Sat here for a hour trying to figure out why the cascade wasn't working. I don't use the sync as I hand write the migrations to have better control of the DB. Thanks for the info on this issue. Glad i was able to find it :D |
Desperately waiting for this. For now I had to handle cascade delete manually in model hooks. |
+1 for the feature |
+1 |
1 similar comment
+1 |
+200 |
+1000000000 |
Since 2014 waiting for this feature! |
Well...i just did my part. Enjoy! |
For anyone else looking for an easy solution, the following seems to work just fine: UserGroup.addHook('beforeDestroy', async (group) => {
await group.setUsers([]);
}); If you need to do the same when users are deleted, you would need to set the same hook on the Our model associations are defined as follows: UserGroup.belongsToMany(models.User, {
through: 'UsersInUserGroups',
foreignKey: 'userGroupId',
otherKey: 'userId',
});
User.belongsToMany(models.UserGroup, {
through: 'UsersInUserGroups',
as: 'groups',
foreignKey: 'userId',
otherKey: 'userGroupId',
}); |
i'm surprised this is still not a thing. HOW has this ticket been open for 7 years? I'm starting to get a lil disappointed, maintainers... |
It's been open for 7 years because scalable applications don't handle cascades through an ORM layer. |
@tommybananas What do you mean by this? Are you saying scalable applications don't use an ORM layer? Then they wouldn't be using Sequalize. Or they do but have some of their logic in SQL and others in Javascript? Cause that introduces another scalability issue. |
My take on this is (maybe wrong): We should completely ditch the usage of Instead, we could do the deletions manually:
This approach helps us perform deletion logic using bulk operations therefore making the operation faster and lighter. Correct me if I am wrong, better ideas and comments are welcome. |
I had a new years idea and created this package to try a solution for this issue using triggers. https://github.com/ReMatter/sequelize-paranoid-delete It is in development but I'd like to know your thoughts. |
If you're from the European Union or have customers from the European Union, the right of erasure means you'll have to hard delete some data, not just soft delete. (disclaimer: not a lawyer). |
@nicoabie Of course, using cascading deletes is a matter of personal choice, and having a solution to keep using them is great (although I am a bit worried about performance of your solution on large datasets). But I'd like to bring the focus on a bigger question:
So, my preference is to use soft deletes and handle deletion of related entites manually. Implementation of this may differ. I am currently using the repository pattern and update all related/child entities in root/parent entitie's repository when the root/parent entity is deleted. This way you don't lose database integrity, you are more flexible and ready for future business requirements. As a bonus, your database can tell you how the data has been created, transformed, and deleted at any point of time. You never lose information. There are also drawbacks, like more storage required and more manual work, but you are also always in control, and this is, imho, very useful when working on enterprise solutions. But, as always, it depends 🙂 |
@ephys Agreed. That kind of data can be an exception and may be handled separately.
Quoting from this website. This basically means a separate logic should be implemented for physically removing data on user's request, while using soft deletions in any other use case. But I am not an expert, this is just an assumption. |
Here we are talking for a solution to the unsupported cascade deletes in paranoid mode (meaning setting the deletedAt field) One solution proposed was to use hooks which IMHO will be getting more responsibility than they should. The proposed approach is to automatically creating triggers when running migrations to emulate the cascade in paranoid mode. Is there any other way to do this that isn't cumbersome or error prone? |
Well, my solution is to not have a solution at all for this specific problem. Because deleting related data might be out of the scope of the responsibilities of an ORM library, considering it being an application's own architectural problem. |
@haykerman I truly do not understand what you are saying. "my solution is to not have a solution at all for this specific problem" the whole point of this thread is to find a solution for this problem. No offense or disrespect but have you read this thread? |
I have read the thread and I am well aware of the problem, as I've been investigating it for more than a month now. What I am proposing is implementing deletion logic for related tables in application code, not on database level, because it's business logic. It's neither ORM's nor DB's responsibility to implement/contain this kind of business logic (imo, though this is debated). It's preferable to keep the DB as "dumb" as possible and treat it as a data store (only with some constraints). I am aware that some people implement the solution on DB level (through triggers or stored procedures). As @tommybananas mentioned:
But if it's absolutely necessary and applicable in your (and anyone interested) case, go ahead and implement a solution (as @nicoabie did, BTW good job). To summarize, I don't think an ORM/DB should handle cascading soft deletes. But this is just my opinion. For more details, I propose the community to do their own research on how this kind of problems are solved in existing enterprise solutions, what are the cons and pros. I am always available for discussion (sequelize gitter). |
I really like the trigger suggestion posted above. If it works we should look into importing it inside of sequelize itself. @nicoabie if you're ever interested in porting this inside of Sequelize, let me know :) |
@ephys I can't believe one year passed and I haven't finished that package. We need to support the case of existing projects. I think we could port it into sequelize once it is proven to work. I'll try to work on it more and let you know its status. |
@ephys package has just been published https://www.npmjs.com/package/@rematter/sequelize-paranoid-delete All are welcome to try it and create issues if experiencing problems |
You can overcome this issue by using afterDestroy hook.
|
I have a relationship between two paranoid tables (User and Email) and I have the onDelete: 'cascade' option on the relationship ( Email.belongsTo(User, onDelete:'cascade') ).
The problem is that when I delete the user his email is not being deleted by cascade.
Is this a bug? Or this is how it is supposed to work?
I am using sequelize 2.0.0-rc2 on a postgres database.
Thanks.
PS.: Please take a look at the code I used for test:
The text was updated successfully, but these errors were encountered: