Skip to content

Commit 6c92103

Browse files
authored
Fix JSONField has key lookup
1 parent 0153047 commit 6c92103

File tree

2 files changed

+39
-9
lines changed

2 files changed

+39
-9
lines changed

mssql/functions.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,9 @@
1212
from django.db.models import lookups
1313

1414
if VERSION >= (3, 1):
15-
from django.db.models.fields.json import KeyTransform, KeyTransformIn, KeyTransformExact
15+
from django.db.models.fields.json import (
16+
KeyTransform, KeyTransformIn, KeyTransformExact,
17+
HasKeyLookup, compile_json_path)
1618

1719
DJANGO3 = VERSION[0] >= 3
1820

@@ -134,11 +136,42 @@ def json_KeyTransformIn(self, compiler, connection):
134136

135137
return (lhs + ' IN ' + rhs, unquote_json_rhs(rhs_params))
136138

139+
def json_HasKeyLookup(self, compiler, connection):
140+
# Process JSON path from the left-hand side.
141+
if isinstance(self.lhs, KeyTransform):
142+
lhs, _, lhs_key_transforms = self.lhs.preprocess_lhs(compiler, connection)
143+
lhs_json_path = compile_json_path(lhs_key_transforms)
144+
else:
145+
lhs, _ = self.process_lhs(compiler, connection)
146+
lhs_json_path = '$'
147+
sql = lhs + ' IN (SELECT ' + lhs + ' FROM ' + self.lhs.output_field.model._meta.db_table + \
148+
' CROSS APPLY OPENJSON(' + lhs + ') WITH ( [json_path_value] char(1) \'%s\') WHERE [json_path_value] IS NOT NULL)'
149+
# Process JSON path from the right-hand side.
150+
rhs = self.rhs
151+
rhs_params = []
152+
if not isinstance(rhs, (list, tuple)):
153+
rhs = [rhs]
154+
for key in rhs:
155+
if isinstance(key, KeyTransform):
156+
*_, rhs_key_transforms = key.preprocess_lhs(compiler, connection)
157+
else:
158+
rhs_key_transforms = [key]
159+
rhs_params.append('%s%s' % (
160+
lhs_json_path,
161+
compile_json_path(rhs_key_transforms, include_root=False),
162+
))
163+
# Add condition for each key.
164+
if self.logical_operator:
165+
sql = '(%s)' % self.logical_operator.join([sql] * len(rhs_params))
166+
167+
return sql % tuple(rhs_params), []
168+
137169
ATan2.as_microsoft = sqlserver_atan2
138170
In.split_parameter_list_as_sql = split_parameter_list_as_sql
139171
if VERSION >= (3, 1):
140172
KeyTransformIn.as_microsoft = json_KeyTransformIn
141173
KeyTransformExact.process_rhs = json_KeyTransformExact_process_rhs
174+
HasKeyLookup.as_microsoft = json_HasKeyLookup
142175
Ln.as_microsoft = sqlserver_ln
143176
Log.as_microsoft = sqlserver_log
144177
Mod.as_microsoft = sqlserver_mod

testapp/settings.py

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -191,28 +191,25 @@
191191
'datetimes.tests.DateTimesTests.test_21432',
192192

193193
#JSONFields
194-
'model_fields.test_jsonfield.TestQuerying.test_has_any_keys',
195-
'model_fields.test_jsonfield.TestQuerying.test_has_key',
196-
'model_fields.test_jsonfield.TestQuerying.test_has_key_deep',
197194
'model_fields.test_jsonfield.TestQuerying.test_has_key_list',
198195
'model_fields.test_jsonfield.TestQuerying.test_has_key_null_value',
199-
'model_fields.test_jsonfield.TestQuerying.test_has_keys',
200-
'model_fields.test_jsonfield.TestQuerying.test_key_iregex',
201196
'model_fields.test_jsonfield.TestQuerying.test_key_quoted_string',
202-
'model_fields.test_jsonfield.TestQuerying.test_key_regex',
203197
'model_fields.test_jsonfield.TestQuerying.test_lookups_with_key_transform',
204198
'model_fields.test_jsonfield.TestQuerying.test_ordering_grouping_by_count',
205199
'model_fields.test_jsonfield.JSONFieldTests.test_db_check_constraints',
206200
'model_fields.test_jsonfield.TestQuerying.test_isnull_key',
207201
'model_fields.test_jsonfield.TestQuerying.test_none_key',
208202
'model_fields.test_jsonfield.TestQuerying.test_none_key_and_exact_lookup',
209-
'model_fields.test_jsonfield.TestQuerying.test_ordering_by_transform',
210203
'model_fields.test_jsonfield.TestQuerying.test_key_escape',
204+
205+
'model_fields.test_jsonfield.TestQuerying.test_ordering_by_transform',
211206
]
212207

213208
REGEX_TESTS = ['lookup.tests.LookupTests.test_regex',
214209
'lookup.tests.LookupTests.test_regex_backreferencing',
215210
'lookup.tests.LookupTests.test_regex_non_ascii',
216211
'lookup.tests.LookupTests.test_regex_non_string',
217-
'lookup.tests.LookupTests.test_regex_null'
212+
'lookup.tests.LookupTests.test_regex_null',
213+
'model_fields.test_jsonfield.TestQuerying.test_key_iregex',
214+
'model_fields.test_jsonfield.TestQuerying.test_key_regex',
218215
]

0 commit comments

Comments
 (0)