expressions.py 2.1 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576
  1. """
  2. This file contains Microsoft SQL Server specific aggregates and overrides for
  3. the default Django aggregates.
  4. """
  5. from django.db.models.aggregates import Avg, StdDev, Variance
  6. from django.db.models.expressions import Value
  7. from django.db.models.functions import Length, Substr
  8. def as_microsoft(expression):
  9. """
  10. Decorated function is added to the provided expression as the Microsoft
  11. vender specific as_sql override.
  12. """
  13. def dec(func):
  14. setattr(expression, 'as_microsoft', func)
  15. return func
  16. return dec
  17. # Aggregates
  18. @as_microsoft(Avg)
  19. def cast_avg_to_float(self, compiler, connection):
  20. """
  21. Microsoft AVG doesn't cast type by default, but needs to CAST to FLOAT so
  22. that AVG([1, 2]) == 1.5, instead of 1.
  23. """
  24. if getattr(connection, 'cast_avg_to_float', True):
  25. return self.as_sql(compiler, connection, template='%(function)s(CAST(%(field)s AS FLOAT))')
  26. return self.as_sql(compiler, connection)
  27. @as_microsoft(StdDev)
  28. def fix_stddev_function_name(self, compiler, connection):
  29. """
  30. Fix function names to 'STDEV' or 'STDEVP' as used by mssql
  31. """
  32. function = 'STDEV'
  33. if self.function == 'STDDEV_POP':
  34. function = 'STDEVP'
  35. return self.as_sql(compiler, connection, function=function)
  36. @as_microsoft(Variance)
  37. def fix_variance_function_name(self, compiler, connection):
  38. """
  39. Fix function names to 'VAR' or 'VARP' as used by mssql
  40. """
  41. function = 'VAR'
  42. if self.function == 'VAR_POP':
  43. function = 'VARP'
  44. return self.as_sql(compiler, connection, function=function)
  45. # Expressions
  46. # Functions
  47. @as_microsoft(Length)
  48. def fix_length_function_name(self, compiler, connection):
  49. """
  50. T-SQL LEN()
  51. """
  52. self.function = 'LEN'
  53. return self.as_sql(compiler, connection)
  54. @as_microsoft(Substr)
  55. def ensure_three_substring_arguments(self, compiler, connection):
  56. """
  57. T-SQL SUBSTRING() requires 3 arguments. length is never implied.
  58. """
  59. if len(self.source_expressions) == 2:
  60. self.source_expressions.append(Value(2 ** 31 - 1))
  61. return self.as_sql(compiler, connection)