﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
36034	ForeignKey to CompositePrimaryKey crashes.	Mariusz Felisiak	Mariusz Felisiak	"I've created a sample project that tries to create a foreign key to the table with `CompositePrimaryKey`:
{{{
class Release(models.Model):
    pk = models.CompositePrimaryKey(""version"", ""name"")
    version = models.IntegerField()
    name = models.CharField(max_length=20)


class RefRelease(models.Model):
    release = models.ForeignKey(""Release"", models.CASCADE)

}}}

It doesn't work (because #35956 is not implemented):

{{{
$ python manage.py sqlmigrate test_one 0001
BEGIN;
--
-- Create model Release
--
CREATE TABLE ""test_one_release"" (""version"" integer NOT NULL, ""name"" varchar(20) NOT NULL, PRIMARY KEY (""version"", ""name""));
--
-- Create model RefRelease
--
CREATE TABLE ""test_one_refrelease"" (""id"" integer NOT NULL PRIMARY KEY AUTOINCREMENT);
CREATE INDEX ""test_one_refrelease_release_id_f24095be"" ON ""test_one_refrelease"" (""release_id"");
COMMIT;
}}}

`FOREIGN KEY` has not been created in `""test_one_refrelease""`:

{{{
$ python manage.py dbshell
sqlite> pragma table_info(test_one_refrelease);
0|id|INTEGER|1||1
sqlite> pragma table_info(test_one_release);
0|version|INTEGER|1||1
1|name|varchar(20)|1||2
sqlite>
}}}

and any attempt to create a new object crashes:
{{{
$ python manage.py shell
>>> from test_one.models import *
>>> r =  Release.objects.create(version=3, name=""y"")
>>> RefRelease.objects.create(release=r)
Traceback (most recent call last):
  File ""/django/django/db/backends/utils.py"", line 105, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/sqlite3/base.py"", line 360, in execute
    return super().execute(query, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: table test_one_refrelease has no column named release_id

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File ""/django/django/db/backends/utils.py"", line 134, in debug_sql
    yield
  File ""/django/django/db/backends/utils.py"", line 122, in execute
    return super().execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/utils.py"", line 79, in execute
    return self._execute_with_wrappers(
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/utils.py"", line 92, in _execute_with_wrappers
    return executor(sql, params, many, context)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/utils.py"", line 100, in _execute
    with self.db.wrap_database_errors:
  File ""/django/django/db/utils.py"", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File ""/django/django/db/backends/utils.py"", line 105, in _execute
    return self.cursor.execute(sql, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/sqlite3/base.py"", line 360, in execute
    return super().execute(query, params)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
django.db.utils.OperationalError: table test_one_refrelease has no column named release_id

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File ""<console>"", line 1, in <module>
  File ""/django/django/db/models/manager.py"", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/query.py"", line 663, in create
    obj.save(force_insert=True, using=self.db)
  File ""/django/django/db/models/base.py"", line 901, in save
    self.save_base(
  File ""/django/django/db/models/base.py"", line 1007, in save_base
    updated = self._save_table(
              ^^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/base.py"", line 1170, in _save_table
    results = self._do_insert(
              ^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/base.py"", line 1211, in _do_insert
    return manager._insert(
           ^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/manager.py"", line 87, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/query.py"", line 1849, in _insert
    return query.get_compiler(using=using).execute_sql(returning_fields)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/models/sql/compiler.py"", line 1891, in execute_sql
    cursor.execute(sql, params)
  File ""/django/django/db/backends/utils.py"", line 121, in execute
    with self.debug_sql(sql, params, use_last_executed_query=True):
  File ""/usr/local/lib/python3.12/contextlib.py"", line 158, in __exit__
    self.gen.throw(value)
  File ""/django/django/db/backends/utils.py"", line 139, in debug_sql
    sql = self.db.ops.last_executed_query(self.cursor, sql, params)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/sqlite3/operations.py"", line 178, in last_executed_query
    params = self._quote_params_for_last_executed_query(params)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File ""/django/django/db/backends/sqlite3/operations.py"", line 167, in _quote_params_for_last_executed_query
    return cursor.execute(sql, params).fetchone()
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.ProgrammingError: Error binding parameter 1: type 'tuple' is not supported
}}}


IMO, we should at least raise an error (system check) in such cases. For now, migrations are proceeding without any indication that anything went wrong."	Bug	closed	Database layer (models, ORM)	dev	Release blocker	fixed			Ready for checkin	1	0	0	0	0	0
