Opened 22 months ago

Closed 21 months ago

Last modified 14 months ago

#34320 closed Bug (fixed)

Renaming fields with truncated names don't remove old constraints on Oracle.

Reported by: Georgi Yanchev Owned by: Mohamed Nabil Rady
Component: Database layer (models, ORM) Version: 4.1
Severity: Normal Keywords: oracle
Cc: Triage Stage: Ready for checkin
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

Steps to reproduce:

  1. Use Oracle as a db backend
  1. Create a model class:
    class TestModel(models.Model):
        looooooooooooooooooooooooooooooooooooooong_name = models.PositiveIntegerField(default=0)
    
  1. python manage.py makemigrations

You get a migration file called 0001_initial.py with:

    operations = [
        migrations.CreateModel(
            name='TestModel',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('looooooooooooooooooooooooooooooooooooooong_name', models.PositiveIntegerField(default=0)),
            ],
        ),
    ]

  1. Rename the field in the model:
    class TestModel(models.Model):
        renamed_looooooooooooooooooooooooooooooooooooooong_name = models.PositiveIntegerField(default=0)
    
  1. python manage.py makemigrations

When asked about whether the field was renamed, say "y".
You get another migrations file 0002_rename_looooooooooooooooooooooooooooooooooooooong_name_testmodel_renamed_loooooooooooooooooooooooooo.py with:

    operations = [
        migrations.RenameField(
            model_name='testmodel',
            old_name='looooooooooooooooooooooooooooooooooooooong_name',
            new_name='renamed_looooooooooooooooooooooooooooooooooooooong_name',
        ),
    ]
  1. Migrate db

python manage.py migrate myapp
The queries executed are:

-- 0001_....py
CREATE TABLE "MYAPP_TESTMODEL" ("ID" NUMBER(19) GENERATED BY DEFAULT ON NULL AS IDENTITY NOT NULL PRIMARY KEY, "LOOOOOOOOOOOOOOOOOOOOOOOOO8973" NUMBER(11) NOT NULL CHECK ("LOOOOOOOOOOOOOOOOOOOOOOOOO8973" >= 0))

-- 0002_....py
ALTER TABLE "MYAPP_TESTMODEL" RENAME COLUMN "LOOOOOOOOOOOOOOOOOOOOOOOOO8973" TO "RENAMED_LOOOOOOOOOOOOOOOOOAFEA"
ALTER TABLE "MYAPP_TESTMODEL" ADD CONSTRAINT "MYAPP_TES_RENAMED_L_7E971FCA_C" CHECK ("RENAMED_LOOOOOOOOOOOOOOOOOAFEA" >= 0)

Note that we didn't create a constraint when applying 0001, but we did create one for 0002. So the db schema is not the same as it would be if 0001 and 0002 were squashed

  1. Unapply 0002

python manage.py migrate myapp 0001
Queries are:

ALTER TABLE "MYAPP_TESTMODEL" RENAME COLUMN "RENAMED_LOOOOOOOOOOOOOOOOOAFEA" TO "LOOOOOOOOOOOOOOOOOOOOOOOOO8973"
ALTER TABLE "MYAPP_TESTMODEL" ADD CONSTRAINT "MYAPP_TES_LOOOOOOOO_D76B28D1_C" CHECK ("LOOOOOOOOOOOOOOOOOOOOOOOOO8973" >= 0)

Note that MYAPP_TES_RENAMED_L_7E971FCA_C that was created when 0002 was applied is not dropped. So now we end up with 2 CONSTRAINTs.

  1. Apply 0002

python migrate myapp 0002

Queries are:

ALTER TABLE "MYAPP_TESTMODEL" RENAME COLUMN "LOOOOOOOOOOOOOOOOOOOOOOOOO8973" TO "RENAMED_LOOOOOOOOOOOOOOOOOAFEA"
ALTER TABLE "MYAPP_TESTMODEL" ADD CONSTRAINT "MYAPP_TES_RENAMED_L_7E971FCA_C" CHECK ("RENAMED_LOOOOOOOOOOOOOOOOOAFEA" >= 0)

Observed:

The last query fails with:

django.db.utils.DatabaseError: ORA-02264: name already used by an existing constraint

Expected:

  1. Database schema is the same no matter whether a field was renamed.
  2. Obsolete db CONSTRAINTs are dropped.

Change History (13)

comment:1 by Georgi Yanchev, 22 months ago

Summary: Oracle migrations don't remove CONSTRAINTsOracle rename field migrations don't remove CONSTRAINTs

comment:2 by Georgi Yanchev, 22 months ago

Summary: Oracle rename field migrations don't remove CONSTRAINTsOracle rename field migrations don't remove old CONSTRAINTs

comment:3 by Mariusz Felisiak, 22 months ago

Keywords: oracle added
Summary: Oracle rename field migrations don't remove old CONSTRAINTsRenaming fields with truncated names don't remove old constraints on Oracle.
Triage Stage: UnreviewedAccepted

Thanks for the report. As far as I'm aware, the main reason is that BaseDatabaseSchemaEditor._constraint_names() doesn't use truncated column names.

comment:4 by Mohamed Nabil Rady, 21 months ago

Owner: changed from nobody to Mohamed Nabil Rady
Status: newassigned

comment:5 by Mohamed Nabil Rady, 21 months ago

Has patch: set

comment:6 by Mariusz Felisiak, 21 months ago

Needs tests: set

comment:7 by Mariusz Felisiak, 21 months ago

Needs tests: unset
Triage Stage: AcceptedReady for checkin

comment:8 by Mariusz Felisiak <felisiak.mariusz@…>, 21 months ago

Resolution: fixed
Status: assignedclosed

In 6bdc3c58:

Fixed #34320 -- Make sure constraints names are obtained from truncated columns names.

comment:9 by Mariusz Felisiak <felisiak.mariusz@…>, 21 months ago

In 3b09f355:

[4.2.x] Fixed #34320 -- Make sure constraints names are obtained from truncated columns names.

Backport of 6bdc3c58b65eb32fd63cd41849f00a17a36b4473 from main

comment:10 by GitHub <noreply@…>, 21 months ago

In 40e88ae:

Refs #34320 -- Added skipIf for a test requiring check constraints.

comment:11 by Mariusz Felisiak <felisiak.mariusz@…>, 21 months ago

In fae76b81:

[4.2.x] Refs #34320 -- Added skipIf for a test requiring check constraints.

Backport of 40e88ae8c899bcae3a9520f7a6519dd178185f85 from main

comment:12 by GitHub <noreply@…>, 21 months ago

In 9953c804:

Refs #34320 -- Stopped recreating check constraints when renaming fields.

This also fixes test_rename_field_with_check_to_truncated_name() on
MariaDB 10.5.2+ as ALTER TABLE ... RENAME COLUMN statement doesn't
rename inline constraints.

comment:13 by GitHub <noreply@…>, 14 months ago

In fec4ed0a:

[4.2.x] Refs #34320 -- Skipped SchemaTests.test_rename_field_with_check_to_truncated_name on MariaBD 10.5.2+.

This crashes since MariaDB was bumped to 10.5 on Jenkins.

Note: See TracTickets for help on using tickets.
Back to Top