99import time
1010import struct
1111import datetime
12+ from decimal import Decimal
13+ from uuid import UUID
1214
1315from django .core .exceptions import ImproperlyConfigured
1416from django .utils .functional import cached_property
@@ -571,6 +573,36 @@ def __init__(self, cursor, connection):
571573 self .last_sql = ''
572574 self .last_params = ()
573575
576+ def _as_sql_type (self , typ , value ):
577+ if isinstance (value , str ):
578+ length = len (value )
579+ if length == 0 :
580+ return 'NVARCHAR'
581+ elif length > 4000 :
582+ return 'NVARCHAR(max)'
583+ return 'NVARCHAR(%s)' % len (value )
584+ elif typ == int :
585+ if value < 0x7FFFFFFF and value > - 0x7FFFFFFF :
586+ return 'INT'
587+ else :
588+ return 'BIGINT'
589+ elif typ == float :
590+ return 'DOUBLE PRECISION'
591+ elif typ == bool :
592+ return 'BIT'
593+ elif isinstance (value , Decimal ):
594+ return 'NUMERIC'
595+ elif isinstance (value , datetime .datetime ):
596+ return 'DATETIME2'
597+ elif isinstance (value , datetime .date ):
598+ return 'DATE'
599+ elif isinstance (value , datetime .time ):
600+ return 'TIME'
601+ elif isinstance (value , UUID ):
602+ return 'uniqueidentifier'
603+ else :
604+ raise NotImplementedError ('Not supported type %s (%s)' % (type (value ), repr (value )))
605+
574606 def close (self ):
575607 if self .active :
576608 self .active = False
@@ -588,6 +620,27 @@ def format_sql(self, sql, params):
588620
589621 return sql
590622
623+ def format_group_by_params (self , query , params ):
624+ if params :
625+ # Insert None params directly into the query
626+ if None in params :
627+ null_params = ['NULL' if param is None else '%s' for param in params ]
628+ query = query % tuple (null_params )
629+ params = tuple (p for p in params if p is not None )
630+ params = [(param , type (param )) for param in params ]
631+ params_dict = {param : '@var%d' % i for i , param in enumerate (set (params ))}
632+ args = [params_dict [param ] for param in params ]
633+
634+ variables = []
635+ params = []
636+ for key , value in params_dict .items ():
637+ datatype = self ._as_sql_type (key [1 ], key [0 ])
638+ variables .append ("%s %s = %%s " % (value , datatype ))
639+ params .append (key [0 ])
640+ query = ('DECLARE %s \n ' % ',' .join (variables )) + (query % tuple (args ))
641+
642+ return query , params
643+
591644 def format_params (self , params ):
592645 fp = []
593646 if params is not None :
@@ -616,6 +669,8 @@ def format_params(self, params):
616669
617670 def execute (self , sql , params = None ):
618671 self .last_sql = sql
672+ if 'GROUP BY' in sql :
673+ sql , params = self .format_group_by_params (sql , params )
619674 sql = self .format_sql (sql , params )
620675 params = self .format_params (params )
621676 self .last_params = params
0 commit comments