IMO it would be safer to cause error while applying the migration rather than ending in unexpected state of DB. Developer would know all consequences about RemoveField operation in advance and could take appropriate countermeasures to apply this operation without side effects.
Hello there, i just want to contribute to this, not having a solid opinion on it.
I believe that the problem is that, most of these side effects will be only knew about on production, taking the scenario of having a view on your production database, is likely that the developer won’t have any views on his local database. Making this really hard to spot, even if you’re removing the CASCADE from the operation.
If you really want to strict this, you can always monkey patch the SQL string on the schema class anyway.
I think that it is good practise to have views in migrations as well. So they should be on your local DB too and cause error while developing or in CI test phase.
Otherwise, it could fall at least in staging environment while applying migrations. Or, in the last, in production environment where could be better to stop migrations with side effects rather than have missing of half of the views without knowing what the hack has just happened
@petrprikryl I think that preventing database objects not managed by Django from being deleted is a good enough reason to revisit the inclusion of CASCADE.
My concerns though are that it’s not as simple as removing the suffix and calling it a day, there is likely a reason why it’s being used. Did you do a bit of Git-archeology through git-blame or tried running the test suite to understand why it’s being used?
Understanding why it’s the case and what it can be replaced with would make for a stronger and better informed case than solely reporting the problem it poses to your workflow.
I tried to find why it is in Django before sending the post. But only found that it is there from first commit of schema alteration without any more information:
Drop table now cascades by default, as this is usually the intended behaviour. You can pass cascade=False to stop this.
I didn’t tried to run test suit as I wanted to get some more information and opinion from community about this problem first. Maybe @andrewgodwin could bring some light here.
So I found out that one use case for cascade on sql_delete_table is automatic dropping of constraints.
django-docker-box for postgres after removing cascade:
ERROR [0.000s]: test_unsupported_transactional_ddl_disallowed (schema.tests.SchemaTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tests/django/django/db/backends/utils.py", line 103, in _execute
return self.cursor.execute(sql)
File "/usr/local/lib/python3.10/site-packages/psycopg/cursor.py", line 732, in execute
raise ex.with_traceback(None)
psycopg.errors.DependentObjectsStillExist: cannot drop table schema_authorwithevenlongername because other objects depend on it
DETAIL: constraint schema_bookwithlongn_author_foreign_key_w_14c57257_fk_schema_au on table schema_bookwithlongname depends on table schema_authorwithevenlongername
constraint schema_bookwithlongn_author_other_really__6c36f4d2_fk_schema_au on table schema_bookwithlongname depends on table schema_authorwithevenlongername
HINT: Use DROP ... CASCADE to drop the dependent objects too.
So constraints would have to be removed manually. Maybe with help of pg_get_constraintdefpostgresql - Retrieving all PK and FK - Database Administrators Stack Exchange. But it starting to look like too postgres specific and I am not sure if there is any interest for this change. I’m looking forward to hearing your opinions.
Removing cascade on sql_delete_column seems to have no impact on test suite for postgres, sqlite and mariadb databases.
My gut reaction is that the CASCADE option is the most sensible default.
In addition to views, constraints and the foreign key references, there could also be indexes, formulas for calculated columns, functions, procedures, and triggers to name a few - all of which may need to be deleted when a column or table is dropped.
Next, Django is dropping the constraints explicitly. So cascade shouldn’t be needed. It explains why my test suite was passing after removing cascade from sql_delete_column (my previous post).