diff options
| author | Simon Charette <charette.s@gmail.com> | 2019-03-16 13:48:59 -0400 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-03-18 09:32:09 +0100 |
| commit | 883d87074dd916224e2436ecc3dad8dd80e87c16 (patch) | |
| tree | 6e78bc9a0c31b68afdb206cd896dd252b5821a78 | |
| parent | 2a92e2e3c12e5c4cad0ce2a2d5964675ef837fe7 (diff) | |
[2.2.x] Fixed #30258 -- Adjusted postgres schema value quoting of ranges.
Thanks Tilman Koschnick for the report and patch.
Backport of 386d89ab55e620440d30590a8a104fe6d5eef830 from master
| -rw-r--r-- | django/db/backends/postgresql/schema.py | 3 | ||||
| -rw-r--r-- | tests/postgres_tests/test_constraints.py | 35 |
2 files changed, 37 insertions, 1 deletions
diff --git a/django/db/backends/postgresql/schema.py b/django/db/backends/postgresql/schema.py index 9eecaac19a..a81fd314e3 100644 --- a/django/db/backends/postgresql/schema.py +++ b/django/db/backends/postgresql/schema.py @@ -22,7 +22,8 @@ class DatabaseSchemaEditor(BaseDatabaseSchemaEditor): sql_delete_procedure = 'DROP FUNCTION %(procedure)s(%(param_types)s)' def quote_value(self, value): - return psycopg2.extensions.adapt(value) + # getquoted() returns a quoted byte string of the adapted value. + return psycopg2.extensions.adapt(value).getquoted().decode() def _field_indexes_sql(self, model, field): output = super()._field_indexes_sql(model, field) diff --git a/tests/postgres_tests/test_constraints.py b/tests/postgres_tests/test_constraints.py new file mode 100644 index 0000000000..0e09a1c546 --- /dev/null +++ b/tests/postgres_tests/test_constraints.py @@ -0,0 +1,35 @@ +from django.db import connection, transaction +from django.db.models import Q +from django.db.models.constraints import CheckConstraint +from django.db.utils import IntegrityError + +from . import PostgreSQLTestCase +from .models import RangesModel + +try: + from psycopg2.extras import NumericRange +except ImportError: + pass + + +class SchemaTests(PostgreSQLTestCase): + def get_constraints(self, table): + """Get the constraints on the table using a new cursor.""" + with connection.cursor() as cursor: + return connection.introspection.get_constraints(cursor, table) + + def test_check_constraint_range_value(self): + constraint_name = 'ints_between' + self.assertNotIn(constraint_name, self.get_constraints(RangesModel._meta.db_table)) + constraint = CheckConstraint( + check=Q(ints__contained_by=NumericRange(10, 30)), + name=constraint_name, + ) + with connection.schema_editor() as editor: + editor.add_constraint(RangesModel, constraint) + with connection.cursor() as cursor: + constraints = connection.introspection.get_constraints(cursor, RangesModel._meta.db_table) + self.assertIn(constraint_name, constraints) + with self.assertRaises(IntegrityError), transaction.atomic(): + RangesModel.objects.create(ints=(20, 50)) + RangesModel.objects.create(ints=(10, 30)) |
