3YOURMIND / django-add-default-value

This django Migration Operation can be used to transfer a Fields default value to the database scheme.
Apache License 2.0
138 stars 20 forks source link

Broken quotes with multiple databases #11

Closed David-Wobrock closed 5 years ago

David-Wobrock commented 5 years ago

Hi,

On a Django project that defines multiple databases, the quotes are broken.

Defining

DATABASES = {
    'mysql': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'mydb',
        [...]
    },
    'postgresql': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'db',
        [...]
   },
}

One app has a migration that looks like

    operations = [
        migrations.AddField(
            model_name='a',
            name='not_null_field',
            field=models.IntegerField(default=1),
        ),
        AddDefaultValue(
            model_name='a',
            name='not_null_field',
            value=1,
        )
    ]

Launching the tests, which will set up both databases, we get the error

django.db.utils.ProgrammingError: syntax error at or near "`"                                                                                                                                               
LINE 1: ALTER TABLE `app_add_not_null_column_followed_by_default_a` ... 

Investigation: Introspecting the SQL queries that are sent to the database:

and to the postgresql DB:

ALTER TABLE "app_add_not_null_column_followed_by_default_a" ADD COLUMN "not_null_field" integer DEFAULT %s NOT NULL                                                                                         
ALTER TABLE "app_add_not_null_column_followed_by_default_a" ALTER COLUMN "not_null_field" DROP DEFAULT                                                                                                      
ALTER TABLE `app_add_not_null_column_followed_by_default_a` ALTER COLUMN `not_null_field` SET DEFAULT '1';

where the last line obviously is incorrect.

Thank you for your time :) David

David-Wobrock commented 5 years ago

And funnily enough, since we have badly isolated logic, when you change the order of the databases in the settings, it works for some cases (even though, the dict are unordered. From one version of Python to another, the behaviours changes). Probably because mysql accepts the same quotes as postgresql, but postgresql does not accept the mysql quotes :+1:

So I got a workaround in some edge cases at least ;)