@@ -249,6 +249,7 @@ def json_HasKeyLookup(self, compiler, connection):
249249 """
250250
251251 def _combine_conditions (conditions ):
252+ # Combine multiple conditions with the logical operator if present, else return the first condition
252253 if hasattr (self , 'logical_operator' ) and self .logical_operator :
253254 logical_op = f" { self .logical_operator } "
254255 return f"({ logical_op .join (conditions )} )"
@@ -257,10 +258,12 @@ def _combine_conditions(conditions):
257258
258259 # Process JSON path from the left-hand side.
259260 if isinstance (self .lhs , KeyTransform ):
261+ # If lhs is a KeyTransform, preprocess to get SQL and JSON path
260262 lhs , _ , lhs_key_transforms = self .lhs .preprocess_lhs (compiler , connection )
261263 lhs_json_path = compile_json_path (lhs_key_transforms )
262264 lhs_params = []
263265 else :
266+ # Otherwise, process lhs normally
264267 lhs , lhs_params = self .process_lhs (compiler , connection )
265268 lhs_json_path = '$'
266269
@@ -270,21 +273,26 @@ def _combine_conditions(conditions):
270273 # Process JSON paths from the right-hand side
271274 rhs = self .rhs
272275 if not isinstance (rhs , (list , tuple )):
276+ # Ensure rhs is a list for uniform processing
273277 rhs = [rhs ]
274278
275279 rhs_params = []
276280 for key in rhs :
277281 if isinstance (key , KeyTransform ):
282+ # If key is a KeyTransform, preprocess to get JSON path
278283 * _ , rhs_key_transforms = key .preprocess_lhs (compiler , connection )
279284 else :
285+ # Otherwise, treat key as a single transform
280286 rhs_key_transforms = [key ]
281287
282288 if VERSION >= (4 , 1 ):
289+ # For Django 4.1+, split out the final key and compile the path
283290 * rhs_key_transforms , final_key = rhs_key_transforms
284291 rhs_json_path = compile_json_path (rhs_key_transforms , include_root = False )
285292 rhs_json_path += self .compile_json_path_final_key (final_key )
286293 rhs_params .append (lhs_json_path + rhs_json_path )
287294 else :
295+ # For older Django, just compile the path
288296 rhs_params .append (
289297 '%s%s' % (
290298 lhs_json_path ,
@@ -297,28 +305,36 @@ def _combine_conditions(conditions):
297305 params = []
298306 conditions = []
299307 if is_cast_expression :
308+ # If lhs is a Cast, get its SQL and params
300309 cast_sql , cast_params = self .lhs .as_sql (compiler , connection )
301310
302311 for path in rhs_params :
312+ # Escape single quotes in the path
303313 path_escaped = path .replace ("'" , "''" )
314+ # Build the JSON_PATH_EXISTS condition
304315 conditions .append (f"JSON_PATH_EXISTS({ cast_sql } , '{ path_escaped } ') > 0" )
305316 params .extend (cast_params )
306317
307318 return _combine_conditions (conditions ), params
308319 else :
309320 for path in rhs_params :
321+ # Escape single quotes in the path
310322 path_escaped = path .replace ("'" , "''" )
323+ # Build the JSON_PATH_EXISTS condition using lhs
311324 conditions .append ("JSON_PATH_EXISTS(%s, '%s') > 0" % (lhs , path_escaped ))
312325
313326 return _combine_conditions (conditions ), lhs_params
314327
315328 else :
316329 if is_cast_expression :
330+ # If lhs is a Cast and SQL Server is old, just return a dummy condition
317331 return "1=1" , []
318332 else :
319333 conditions = []
320334 for path in rhs_params :
335+ # Escape single quotes in the path
321336 path_escaped = path .replace ("'" , "''" )
337+ # Build the JSON_VALUE IS NOT NULL condition
322338 conditions .append ("JSON_VALUE(%s, '%s') IS NOT NULL" % (lhs , path_escaped ))
323339
324340 return _combine_conditions (conditions ), lhs_params
0 commit comments