Skip to content

Commit 6bf7655

Browse files
committed
Fix JSONField KeyTransformIn, KeyTransformExact
1 parent a8ceb4e commit 6bf7655

File tree

4 files changed

+32
-20
lines changed

4 files changed

+32
-20
lines changed

azure-pipelines.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ jobs:
1717
- job: Windows
1818
pool:
1919
Django-agent-pool
20+
timeoutInMinutes: 120
2021

2122
strategy:
2223
matrix:

mssql/compiler.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,10 @@ def _as_sql_greatest(self, compiler, connection):
4646
def _as_sql_json_keytransform(self, compiler, connection):
4747
lhs, params, key_transforms = self.preprocess_lhs(compiler, connection)
4848
json_path = compile_json_path(key_transforms)
49-
50-
return 'JSON_VALUE(%s, %%s)' % lhs, tuple(params) + (json_path,)
49+
return (
50+
"COALESCE(JSON_QUERY(%s, '%s'), JSON_VALUE(%s, '%s'))" %
51+
((lhs, json_path) * 2)
52+
), tuple(params) * 2
5153

5254
def _as_sql_least(self, compiler, connection):
5355
# SQL Server does not provide LEAST function,

mssql/functions.py

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,18 @@
11
# Copyright (c) Microsoft Corporation.
22
# Licensed under the MIT license.
33

4+
import json
5+
46
from django import VERSION
57
from django.db.models import BooleanField
68
from django.db.models.functions import Cast
79
from django.db.models.functions.math import ATan2, Log, Ln, Mod, Round
810
from django.db.models.expressions import Case, Exists, OrderBy, When
9-
from django.db.models.lookups import Lookup, In, Exact
11+
from django.db.models.lookups import Lookup, In
12+
from django.db.models import lookups
13+
1014
if VERSION >= (3, 1):
11-
from django.db.models.fields.json import KeyTransform, KeyTransformExact
15+
from django.db.models.fields.json import KeyTransform, KeyTransformIn, KeyTransformExact
1216

1317
DJANGO3 = VERSION[0] >= 3
1418

@@ -110,19 +114,31 @@ def split_parameter_list_as_sql(self, compiler, connection):
110114

111115
return in_clause, ()
112116

113-
def KeyTransformExact_process_rhs(self, compiler, connection):
117+
def unquote_json_rhs(rhs_params):
118+
for value in rhs_params:
119+
value = json.loads(value)
120+
if not isinstance(value, (list, dict)):
121+
rhs_params = [param.replace('"', '') for param in rhs_params]
122+
return rhs_params
123+
124+
def json_KeyTransformExact_process_rhs(self, compiler, connection):
114125
if isinstance(self.rhs, KeyTransform):
115-
return super(Exact, self).process_rhs(compiler, connection)
116-
rhs, rhs_params = super(Exact, self).process_rhs(compiler, connection)
117-
if connection.vendor == 'microsoft':
118-
if rhs_params != [None]:
119-
rhs_params = [params.strip('"') for params in rhs_params]
120-
return rhs, rhs_params
126+
return super(lookups.Exact, self).process_rhs(compiler, connection)
127+
rhs, rhs_params = super(KeyTransformExact, self).process_rhs(compiler, connection)
128+
129+
return rhs, unquote_json_rhs(rhs_params)
130+
131+
def json_KeyTransformIn(self, compiler, connection):
132+
lhs, _ = super(KeyTransformIn, self).process_lhs(compiler, connection)
133+
rhs, rhs_params = super(KeyTransformIn, self).process_rhs(compiler, connection)
134+
135+
return (lhs + ' IN ' + rhs, unquote_json_rhs(rhs_params))
121136

122137
ATan2.as_microsoft = sqlserver_atan2
123138
In.split_parameter_list_as_sql = split_parameter_list_as_sql
124139
if VERSION >= (3, 1):
125-
KeyTransformExact.process_rhs = KeyTransformExact_process_rhs
140+
KeyTransformIn.as_microsoft = json_KeyTransformIn
141+
KeyTransformExact.process_rhs = json_KeyTransformExact_process_rhs
126142
Ln.as_microsoft = sqlserver_ln
127143
Log.as_microsoft = sqlserver_log
128144
Mod.as_microsoft = sqlserver_mod

testapp/settings.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -201,20 +201,13 @@
201201
'model_fields.test_jsonfield.TestQuerying.test_key_quoted_string',
202202
'model_fields.test_jsonfield.TestQuerying.test_key_regex',
203203
'model_fields.test_jsonfield.TestQuerying.test_lookups_with_key_transform',
204-
'model_fields.test_jsonfield.TestQuerying.test_order_grouping_custom_decoder',
205204
'model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count',
206-
'model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_key_transform',
207205
'model_fields.test_jsonfield.JSONFieldTests.test_db_check_constraints',
208206
'model_fields.test_jsonfield.TestQuerying.test_isnull_key',
209-
'model_fields.test_jsonfield.TestQuerying.test_key_in',
210-
'model_fields.test_jsonfield.TestQuerying.test_key_transform_expression',
211-
'model_fields.test_jsonfield.TestQuerying.test_key_values',
212-
'model_fields.test_jsonfield.TestQuerying.test_nested_key_transform_expression',
213207
'model_fields.test_jsonfield.TestQuerying.test_none_key',
214208
'model_fields.test_jsonfield.TestQuerying.test_none_key_and_exact_lookup',
215-
'model_fields.test_jsonfield.TestQuerying.test_none_key_exclude',
216209
'model_fields.test_jsonfield.TestQuerying.test_ordering_by_transform',
217-
'model_fields.test_jsonfield.TestQuerying.test_shallow_lookup_obj_target'
210+
'model_fields.test_jsonfield.TestQuerying.test_key_escape',
218211
]
219212

220213
REGEX_TESTS = ['lookup.tests.LookupTests.test_regex',

0 commit comments

Comments
 (0)