diff options
| author | Florian Hahn <flo@fhahn.com> | 2013-02-21 23:02:18 +0100 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2013-10-22 10:29:57 -0400 |
| commit | 5240b83462ba4887b67da8d493dfdc23fec5df97 (patch) | |
| tree | 7bae13c499bc84b5f4bcf79c592aa2a9b8008033 /django | |
| parent | 1597503a017a9ced422a81d314cb4097d53c3dfd (diff) | |
Fixed #17027 -- Added support for the power operator in F expressions.
Thanks dan at dlo.me for the initial patch.
- Added __pow__ and __rpow__ to ExpressionNode
- Added oracle and mysql specific power expressions
- Added used-defined power function for sqlite
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/backends/mysql/base.py | 8 | ||||
| -rw-r--r-- | django/db/backends/oracle/base.py | 2 | ||||
| -rw-r--r-- | django/db/backends/sqlite3/base.py | 12 | ||||
| -rw-r--r-- | django/db/models/expressions.py | 7 |
4 files changed, 29 insertions, 0 deletions
diff --git a/django/db/backends/mysql/base.py b/django/db/backends/mysql/base.py index 1e3cdbad9b..84bbf1569f 100644 --- a/django/db/backends/mysql/base.py +++ b/django/db/backends/mysql/base.py @@ -386,6 +386,14 @@ class DatabaseOperations(BaseDatabaseOperations): items_sql = "(%s)" % ", ".join(["%s"] * len(fields)) return "VALUES " + ", ".join([items_sql] * num_values) + def combine_expression(self, connector, sub_expressions): + """ + MySQL requires special cases for ^ operators in query expressions + """ + if connector == '^': + return 'POW(%s)' % ','.join(sub_expressions) + return super(DatabaseOperations, self).combine_expression(connector, sub_expressions) + class DatabaseWrapper(BaseDatabaseWrapper): vendor = 'mysql' diff --git a/django/db/backends/oracle/base.py b/django/db/backends/oracle/base.py index a94d95e1ea..6a6a877b46 100644 --- a/django/db/backends/oracle/base.py +++ b/django/db/backends/oracle/base.py @@ -482,6 +482,8 @@ WHEN (new.%(col_name)s IS NULL) return 'BITAND(%s)' % ','.join(sub_expressions) elif connector == '|': raise NotImplementedError("Bit-wise or is not supported in Oracle.") + elif connector == '^': + return 'POWER(%s)' % ','.join(sub_expressions) return super(DatabaseOperations, self).combine_expression(connector, sub_expressions) def _get_sequence_name(self, table): diff --git a/django/db/backends/sqlite3/base.py b/django/db/backends/sqlite3/base.py index ef214234e9..5d07f68f73 100644 --- a/django/db/backends/sqlite3/base.py +++ b/django/db/backends/sqlite3/base.py @@ -304,6 +304,13 @@ class DatabaseOperations(BaseDatabaseOperations): res.extend(["UNION ALL SELECT %s" % ", ".join(["%s"] * len(fields))] * (num_values - 1)) return " ".join(res) + def combine_expression(self, connector, sub_expressions): + # SQLite doesn't have a power function, so we fake it with a + # user-defined function django_power that's registered in connect(). + if connector == '^': + return 'django_power(%s)' % ','.join(sub_expressions) + return super(DatabaseOperations, self).combine_expression(connector, sub_expressions) + class DatabaseWrapper(BaseDatabaseWrapper): vendor = 'sqlite' @@ -376,6 +383,7 @@ class DatabaseWrapper(BaseDatabaseWrapper): conn.create_function("django_datetime_trunc", 3, _sqlite_datetime_trunc) conn.create_function("regexp", 2, _sqlite_regexp) conn.create_function("django_format_dtdelta", 5, _sqlite_format_dtdelta) + conn.create_function("django_power", 2, _sqlite_power) return conn def init_connection_state(self): @@ -567,3 +575,7 @@ def _sqlite_format_dtdelta(dt, conn, days, secs, usecs): def _sqlite_regexp(re_pattern, re_string): return bool(re.search(re_pattern, force_text(re_string))) if re_string is not None else False + + +def _sqlite_power(x, y): + return x ** y diff --git a/django/db/models/expressions.py b/django/db/models/expressions.py index 2fa55b2c14..38b656162d 100644 --- a/django/db/models/expressions.py +++ b/django/db/models/expressions.py @@ -14,6 +14,7 @@ class ExpressionNode(tree.Node): SUB = '-' MUL = '*' DIV = '/' + POW = '^' MOD = '%%' # This is a quoted % operator - it is quoted # because it can be used in strings that also # have parameter substitution. @@ -85,6 +86,9 @@ class ExpressionNode(tree.Node): def __mod__(self, other): return self._combine(other, self.MOD, False) + def __pow__(self, other): + return self._combine(other, self.POW, False) + def __and__(self, other): raise NotImplementedError( "Use .bitand() and .bitor() for bitwise logical operations." @@ -119,6 +123,9 @@ class ExpressionNode(tree.Node): def __rmod__(self, other): return self._combine(other, self.MOD, True) + def __rpow__(self, other): + return self._combine(other, self.POW, True) + def __rand__(self, other): raise NotImplementedError( "Use .bitand() and .bitor() for bitwise logical operations." |
