|
105 | 105 | import django.db # pylint: disable=W0611
|
106 | 106 |
|
107 | 107 | from django.core.exceptions import ImproperlyConfigured
|
108 |
| -from django.db import connection |
| 108 | +from django.db import connection, models |
109 | 109 | from django.db.backends.signals import connection_created
|
110 | 110 | from django.db.utils import DEFAULT_DB_ALIAS, load_backend
|
111 | 111 | from django.utils.safestring import SafeText
|
112 | 112 |
|
113 | 113 | import mysql.connector
|
114 | 114 |
|
115 | 115 | from mysql.connector.conversion import MySQLConverter
|
| 116 | +from mysql.connector.django.base import CursorWrapper |
116 | 117 | from mysql.connector.django.introspection import FieldInfo
|
117 | 118 | from mysql.connector.errors import ProgrammingError
|
118 | 119 |
|
@@ -627,3 +628,58 @@ def test_missing_config(self):
|
627 | 628 | cnx_params = cnx.get_connection_params()
|
628 | 629 | self.assertTrue(cnx_params["raise_on_warnings"])
|
629 | 630 | del settings.DATABASES["default"]["OPTIONS"]
|
| 631 | + |
| 632 | + |
| 633 | +class BugOra37047789(tests.MySQLConnectorTests): |
| 634 | + """BUG#37047789: Python connector does not support Django enum |
| 635 | +
|
| 636 | + Django Enumeration types are not getting converted into MySQLConvertibleType |
| 637 | + thus, query execution via Django ORM using Connector/Python is failing when |
| 638 | + a model field with enum choices are being used. |
| 639 | +
|
| 640 | + This patch fixes the issue by changing the Enum object being passed to the |
| 641 | + conversation module to its underlying value before conversion to MySQL type |
| 642 | + takes place using the built-in property `value`, which already exists in every |
| 643 | + Enum objects. |
| 644 | + """ |
| 645 | + |
| 646 | + table_name = "BugOra37047789" |
| 647 | + |
| 648 | + class Priority(models.IntegerChoices): |
| 649 | + LOW = 1, 'Low' |
| 650 | + MEDIUM = 2, 'Medium' |
| 651 | + HIGH = 3, 'High' |
| 652 | + |
| 653 | + class Status(models.TextChoices): |
| 654 | + DRAFT = 'draft', 'Draft' |
| 655 | + PUBLISHED = 'published', 'Published' |
| 656 | + |
| 657 | + dbconfig = tests.get_mysql_config() |
| 658 | + |
| 659 | + def setUp(self): |
| 660 | + with mysql.connector.connect(**self.dbconfig) as cnx: |
| 661 | + cnx.cmd_query(f""" |
| 662 | + CREATE TABLE {self.table_name} ( |
| 663 | + priority INT NOT NULL DEFAULT 1, |
| 664 | + status varchar(10) NOT NULL DEFAULT 'draft' |
| 665 | + ) |
| 666 | + """) |
| 667 | + cnx.commit() |
| 668 | + |
| 669 | + def tearDown(self): |
| 670 | + with mysql.connector.connect(**self.dbconfig) as cnx: |
| 671 | + cnx.cmd_query(f"DROP TABLE {self.table_name}") |
| 672 | + |
| 673 | + @tests.foreach_cnx() |
| 674 | + def test_django_enum_support(self): |
| 675 | + cnx_cur = self.cnx.cursor() |
| 676 | + django_cur = CursorWrapper(cnx_cur) |
| 677 | + django_cur.execute( |
| 678 | + f"INSERT INTO {self.table_name} VALUES (%s, %s)", |
| 679 | + (self.Priority.HIGH, self.Status.PUBLISHED) |
| 680 | + ) |
| 681 | + django_cur.execute( |
| 682 | + f"INSERT INTO {self.table_name} VALUES (%(priority)s, %(status)s)", |
| 683 | + {'priority': self.Priority.HIGH, 'status': self.Status.PUBLISHED} |
| 684 | + ) |
| 685 | + cnx_cur.close() |
0 commit comments