44import json
55
66from django import VERSION
7-
7+ from django . core import validators
88from django .db import NotSupportedError , connections , transaction
9- from django .db .models import BooleanField , Value
10- from django .db .models .functions import Cast , NthValue
11- from django .db .models .functions .math import ATan2 , Log , Ln , Mod , Round
12- from django .db .models .expressions import Case , Exists , OrderBy , When , Window , Expression
13- from django .db .models .lookups import Lookup , In
14- from django .db .models import lookups , CheckConstraint
9+ from django .db .models import BooleanField , CheckConstraint , Value
10+ from django .db .models .expressions import Case , Exists , Expression , OrderBy , When , Window
1511from django .db .models .fields import BinaryField , Field
16- from django .db .models .sql .query import Query
12+ from django .db .models .functions import Cast , NthValue
13+ from django .db .models .functions .math import ATan2 , Ln , Log , Mod , Round
14+ from django .db .models .lookups import In , Lookup
1715from django .db .models .query import QuerySet
18- from django .core import validators
16+ from django .db . models . sql . query import Query
1917
2018if VERSION >= (3 , 1 ):
2119 from django .db .models .fields .json import (
@@ -67,9 +65,11 @@ def sqlserver_nth_value(self, compiler, connection, **extra_content):
6765def sqlserver_round (self , compiler , connection , ** extra_context ):
6866 return self .as_sql (compiler , connection , template = '%(function)s(%(expressions)s, 0)' , ** extra_context )
6967
68+
7069def sqlserver_random (self , compiler , connection , ** extra_context ):
7170 return self .as_sql (compiler , connection , function = 'RAND' , ** extra_context )
7271
72+
7373def sqlserver_window (self , compiler , connection , template = None ):
7474 # MSSQL window functions require an OVER clause with ORDER BY
7575 if self .order_by is None :
@@ -143,26 +143,29 @@ def split_parameter_list_as_sql(self, compiler, connection):
143143
144144 return in_clause , ()
145145
146+
146147def unquote_json_rhs (rhs_params ):
147148 for value in rhs_params :
148149 value = json .loads (value )
149150 if not isinstance (value , (list , dict )):
150151 rhs_params = [param .replace ('"' , '' ) for param in rhs_params ]
151152 return rhs_params
152153
154+
153155def json_KeyTransformExact_process_rhs (self , compiler , connection ):
154- if isinstance (self .rhs , KeyTransform ):
155- return super (lookups .Exact , self ).process_rhs (compiler , connection )
156- rhs , rhs_params = super (KeyTransformExact , self ).process_rhs (compiler , connection )
156+ rhs , rhs_params = key_transform_exact_process_rhs (self , compiler , connection )
157+ if connection .vendor == 'microsoft' :
158+ rhs_params = unquote_json_rhs (rhs_params )
159+ return rhs , rhs_params
157160
158- return rhs , unquote_json_rhs (rhs_params )
159161
160162def json_KeyTransformIn (self , compiler , connection ):
161163 lhs , _ = super (KeyTransformIn , self ).process_lhs (compiler , connection )
162164 rhs , rhs_params = super (KeyTransformIn , self ).process_rhs (compiler , connection )
163165
164166 return (lhs + ' IN ' + rhs , unquote_json_rhs (rhs_params ))
165167
168+
166169def json_HasKeyLookup (self , compiler , connection ):
167170 # Process JSON path from the left-hand side.
168171 if isinstance (self .lhs , KeyTransform ):
@@ -193,6 +196,7 @@ def json_HasKeyLookup(self, compiler, connection):
193196
194197 return sql % tuple (rhs_params ), []
195198
199+
196200def BinaryField_init (self , * args , ** kwargs ):
197201 # Add max_length option for BinaryField, default to max
198202 kwargs .setdefault ('editable' , False )
@@ -202,6 +206,7 @@ def BinaryField_init(self, *args, **kwargs):
202206 else :
203207 self .max_length = 'max'
204208
209+
205210def _get_check_sql (self , model , schema_editor ):
206211 if VERSION >= (3 , 1 ):
207212 query = Query (model = model , alias_cols = False )
@@ -217,6 +222,7 @@ def _get_check_sql(self, model, schema_editor):
217222
218223 return sql % tuple (schema_editor .quote_value (p ) for p in params )
219224
225+
220226def bulk_update_with_default (self , objs , fields , batch_size = None , default = 0 ):
221227 """
222228 Update the given fields in each of the given objects in the database.
@@ -255,7 +261,7 @@ def bulk_update_with_default(self, objs, fields, batch_size=None, default=0):
255261 attr = getattr (obj , field .attname )
256262 if not isinstance (attr , Expression ):
257263 if attr is None :
258- value_none_counter += 1
264+ value_none_counter += 1
259265 attr = Value (attr , output_field = field )
260266 when_statements .append (When (pk = obj .pk , then = attr ))
261267 if (value_none_counter == len (when_statements )):
@@ -272,10 +278,13 @@ def bulk_update_with_default(self, objs, fields, batch_size=None, default=0):
272278 rows_updated += self .filter (pk__in = pks ).update (** update_kwargs )
273279 return rows_updated
274280
281+
275282ATan2 .as_microsoft = sqlserver_atan2
276283In .split_parameter_list_as_sql = split_parameter_list_as_sql
277284if VERSION >= (3 , 1 ):
278285 KeyTransformIn .as_microsoft = json_KeyTransformIn
286+ # Need copy of old KeyTransformExact.process_rhs to call later
287+ key_transform_exact_process_rhs = KeyTransformExact .process_rhs
279288 KeyTransformExact .process_rhs = json_KeyTransformExact_process_rhs
280289 HasKeyLookup .as_microsoft = json_HasKeyLookup
281290Ln .as_microsoft = sqlserver_ln
0 commit comments