diff options
| author | Luke Plant <L.Plant.98@cantab.net> | 2022-03-31 08:10:22 +0200 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-03-31 11:02:46 +0200 |
| commit | 1efea11808f7b8a3b31445e0c1c7d270f832d965 (patch) | |
| tree | 4f984082f9c70d5fb4d91fd2c655ddcae7c6ef10 | |
| parent | d7eb500338e11999962e618f0701e62af511d8e9 (diff) | |
Refs #33397 -- Added register_combinable_fields().
| -rw-r--r-- | django/db/models/expressions.py | 65 |
1 files changed, 55 insertions, 10 deletions
diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index edd644da54..32982777ef 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -2,6 +2,7 @@ import copy import datetime import functools import inspect +from collections import defaultdict from decimal import Decimal from uuid import UUID @@ -465,16 +466,60 @@ class Expression(BaseExpression, Combinable): return hash(self.identity) -_connector_combinators = { - connector: [ - (fields.IntegerField, fields.IntegerField, fields.IntegerField), - (fields.IntegerField, fields.DecimalField, fields.DecimalField), - (fields.DecimalField, fields.IntegerField, fields.DecimalField), - (fields.IntegerField, fields.FloatField, fields.FloatField), - (fields.FloatField, fields.IntegerField, fields.FloatField), - ] - for connector in (Combinable.ADD, Combinable.SUB, Combinable.MUL, Combinable.DIV) -} +# Type inference for CombinedExpression.output_field. +_connector_combinations = [ + # Numeric operations - operands of same type. + { + connector: [ + (fields.IntegerField, fields.IntegerField, fields.IntegerField), + (fields.FloatField, fields.FloatField, fields.FloatField), + (fields.DecimalField, fields.DecimalField, fields.DecimalField), + ] + for connector in ( + Combinable.ADD, + Combinable.SUB, + Combinable.MUL, + # Behavior for DIV with integer arguments follows Postgres/SQLite, + # not MySQL/Oracle. + Combinable.DIV, + ) + }, + # Numeric operations - operands of different type. + { + connector: [ + (fields.IntegerField, fields.DecimalField, fields.DecimalField), + (fields.DecimalField, fields.IntegerField, fields.DecimalField), + (fields.IntegerField, fields.FloatField, fields.FloatField), + (fields.FloatField, fields.IntegerField, fields.FloatField), + ] + for connector in ( + Combinable.ADD, + Combinable.SUB, + Combinable.MUL, + Combinable.DIV, + ) + }, +] + +_connector_combinators = defaultdict(list) + + +def register_combinable_fields(lhs, connector, rhs, result): + """ + Register combinable types: + lhs <connector> rhs -> result + e.g. + register_combinable_fields( + IntegerField, Combinable.ADD, FloatField, FloatField + ) + """ + _connector_combinators[connector].append((lhs, rhs, result)) + + +for d in _connector_combinations: + for connector, field_types in d.items(): + for lhs, rhs, result in field_types: + register_combinable_fields(lhs, connector, rhs, result) @functools.lru_cache(maxsize=128) |
