#34132: Migration with CheckConstraint fails on PostgreSQL in PyPy with
psycopg2cffi due to AttributeError
-------------------------------------+-------------------------------------
               Reporter:  Henryk     |          Owner:  nobody
  Plötz                              |
                   Type:  Bug        |         Status:  new
              Component:  Database   |        Version:  4.1
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 == Description

 `quote_value` in `django/db/backends/postgresql/schema.py` assigns to
 `adapted.encoding`. This is not allowed in psycopg2cffi and raises an
 AttributeError.

 The code path was added in #31815

 I'm not sure what the correct fix would be. Simply not assigning
 `encoding` seems wrong. Is what the code tries even possible in cffi?

 == Steps to reproduce

 (I'm using poetry. Also needs `apt-get install libpq-dev pypy3 pypy3-dev`
 or equivalent.)

 {{{
 poetry new demo
 cd demo
 poetry env use `which pypy3`
 poetry add django psycopg2cffi
 rm -rf demo
 poetry run django-admin startproject demo
 cd demo
 poetry run ./manage.py startapp demo1
 }}}

 in `demo/settings.py` add

 {{{
 from psycopg2cffi import compat
 compat.register()
 }}}

 and add `demo1` to `INSTALLED_APPS`

 in `demo1/models.py` add


 {{{
 from django.db import models

 # Create your models here.

 class Demo1(models.Model):
   dummy = models.CharField(max_length=23)
   class Meta:
     constraints = [
       models.CheckConstraint(name="dummy",
 check=models.Q(dummy__in=["a","b"]))
     ]
 }}}

 then run


 {{{
 poetry run ./manage.py makemigrations
 }}}


 The file `demo1/migrations/0001_initial.py` now contains


 {{{
 # Generated by Django 4.1.3 on 2022-11-02 10:25

 from django.db import migrations, models


 class Migration(migrations.Migration):

     initial = True

     dependencies = [
     ]

     operations = [
         migrations.CreateModel(
             name='Demo1',
             fields=[
                 ('id', models.BigAutoField(auto_created=True,
 primary_key=True, serialize=False, verbose_name='ID')),
                 ('dummy', models.CharField(max_length=23)),
             ],
         ),
         migrations.AddConstraint(
             model_name='demo1',
             constraint=models.CheckConstraint(check=models.Q(('dummy__in',
 ['a', 'b'])), name='dummy'),
         ),
     ]
 }}}

 Now configure settings for a postgres database (in `demo/settings.py`)


 {{{
 DATABASES = {
     'default': {
         'ENGINE': 'django.db.backends.postgresql',
         'NAME': 'demo',
         "USER": "demo",
         "PASSWORD": "XXXX",
         "HOST": "XXXX",
     }
 }
 }}}

 and run


 {{{
 poetry run ./manage.py migrate
 }}}


 == Actual results


 {{{
 Operations to perform:
   Apply all migrations: admin, auth, contenttypes, demo1, sessions
 Running migrations:
   Applying contenttypes.0001_initial... OK
   Applying auth.0001_initial... OK
   Applying admin.0001_initial... OK
   Applying admin.0002_logentry_remove_auto_add... OK
   Applying admin.0003_logentry_add_action_flag_choices... OK
   Applying contenttypes.0002_remove_content_type_name... OK
   Applying auth.0002_alter_permission_name_max_length... OK
   Applying auth.0003_alter_user_email_max_length... OK
   Applying auth.0004_alter_user_username_opts... OK
   Applying auth.0005_alter_user_last_login_null... OK
   Applying auth.0006_require_contenttypes_0002... OK
   Applying auth.0007_alter_validators_add_error_messages... OK
   Applying auth.0008_alter_user_username_max_length... OK
   Applying auth.0009_alter_user_last_name_max_length... OK
   Applying auth.0010_alter_group_name_max_length... OK
   Applying auth.0011_update_proxy_permissions... OK
   Applying auth.0012_alter_user_first_name_max_length... OK
   Applying demo1.0001_initial...Traceback (most recent call last):
   File "./manage.py", line 22, in <module>
     main()
   File "./manage.py", line 18, in main
     execute_from_command_line(sys.argv)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/core/management/__init__.py", line
 446, in execute_from_command_line
     utility.execute()
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/core/management/__init__.py", line
 440, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/core/management/base.py", line 402,
 in run_from_argv
     self.execute(*args, **cmd_options)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/core/management/base.py", line 448,
 in execute
     output = self.handle(*args, **options)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/core/management/base.py", line 96,
 in wrapped
     res = handle_func(*args, **kwargs)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-
 packages/django/core/management/commands/migrate.py", line 354, in handle
     fake_initial=fake_initial,
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/migrations/executor.py", line
 136, in migrate
     state, plan, full_plan, fake=fake, fake_initial=fake_initial
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/migrations/executor.py", line
 168, in _migrate_all_forwards
     state, migration, fake=fake, fake_initial=fake_initial
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/migrations/executor.py", line
 252, in apply_migration
     state = migration.apply(state, schema_editor)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/migrations/migration.py", line
 131, in apply
     self.app_label, schema_editor, old_state, project_state
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-
 packages/django/db/migrations/operations/models.py", line 1040, in
 database_forwards
     schema_editor.add_constraint(model, self.constraint)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/backends/base/schema.py", line
 511, in add_constraint
     sql = constraint.create_sql(model, self)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/models/constraints.py", line 83,
 in create_sql
     check = self._get_check_sql(model, schema_editor)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/models/constraints.py", line 76,
 in _get_check_sql
     return sql % tuple(schema_editor.quote_value(p) for p in params)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/models/constraints.py", line 76,
 in <genexpr>
     return sql % tuple(schema_editor.quote_value(p) for p in params)
   File "/home/henryk/.cache/pypoetry/virtualenvs/demo-gWrR8tCo-
 py3.8/lib/pypy3.8/site-packages/django/db/backends/postgresql/schema.py",
 line 57, in quote_value
     adapted.encoding = "utf8"
 AttributeError: can't set attribute
 }}}

 == Expected results

 No exception :)

-- 
Ticket URL: <https://code.djangoproject.com/ticket/34132>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/0107018437f124e9-3e3375d0-1cbc-4b61-ba4d-4192867bfce8-000000%40eu-central-1.amazonses.com.

Reply via email to