#34059 closed New feature (fixed)
Validation of check constraints on JSONField key transforms with None produces invalid SQL on PostgreSQL.
| Reported by: | Dan LaManna | Owned by: | David Sanders |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | 4.1 |
| Severity: | Normal | Keywords: | |
| Cc: | David Sanders | Triage Stage: | Accepted |
| Has patch: | yes | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Given a model with constraints within the JSONField:
class Version(models.Model):
metadata = models.JSONField(blank=True, default=dict)
class Meta:
constraints = [
models.CheckConstraint(
name='version_metadata_has_schema_version',
check=~Q(metadata__schemaVersion=None),
)
]
The following code produces an error:
version = Version(metadata={'foo': 'bar'})
version.validate_constraints()
WARNING Got a database error calling check() on <Q: (AND: (NOT (AND: ('metadata__schemaVersion', None))))>: operator is not unique: unknown -> unknown
LINE 1: SELECT 1 AS "_check" WHERE NOT (('{"foo": "bar"}' -> 'schema...
^
HINT: Could not choose a best candidate operator. You might need to add explicit type casts
Internally it's running the following query:
SELECT 1 AS "_check"
WHERE NOT (('{"foo": "bar"}' -> 'schemaVersion') = 'null')
This appears similar to #33905.
Change History (11)
comment:1 by , 3 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 3 years ago
| Cc: | added |
|---|---|
| Component: | contrib.postgres → Database layer (models, ORM) |
| Owner: | set to |
| Status: | new → assigned |
comment:3 by , 3 years ago
| Summary: | Validation of check constraints on postgres json fields produce invalid SQL → Validation of check constraints on PostgreSQL & Oracle JSON fields produces invalid SQL |
|---|
comment:5 by , 3 years ago
| Severity: | Normal → Release blocker |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
Changing component to ORM because this is also an issue with Oracle:
... and JSONField doesn't live in contrib.postgres anymore.
comment:6 by , 3 years ago
| Summary: | Validation of check constraints on PostgreSQL & Oracle JSON fields produces invalid SQL → Validation of check constraints on JSONField key transforms with None produces invalid SQL on PostgreSQL. |
|---|
Validation of json_field__key_transform=None doesn't work only on PostgreSQL. Creating check constraint with __exact lookup e.g. json_field__key_transform="value" crashes on Oracle but it's a separate issue and not a regression (see #34060).
comment:7 by , 3 years ago
| Has patch: | set |
|---|---|
| Patch needs improvement: | set |
PR: https://github.com/django/django/pull/16131
Marking as "needs improvement" as some discussion needs to be had.
comment:8 by , 3 years ago
| Severity: | Release blocker → Normal |
|---|---|
| Type: | Bug → New feature |
comment:10 by , 20 months ago
| Resolution: | → fixed |
|---|---|
| Status: | assigned → closed |
Fixed in 09ffc5c1212d4ced58b708cbbf3dfbfb77b782ca.
Changing component to ORM because this is also an issue with Oracle:
SELECT %s AS "_CHECK" FROM DUAL WHERE NOT (JSON_EXISTS({"foo": "bar"}, '$."schemaVersion"') AND COALESCE(JSON_QUERY(%s, '$."schemaVersion"'), JSON_VALUE(%s, '$."schemaVersion"')) IS NULL) Got a database error calling check() on <Q: (AND: (NOT (AND: ('metadata__schemaVersion', None))))>: ORA-00936: missing expressionMySQL & SQLite are fine