From 3ff39757673b6c1aa8c96c4b951d39afd8e3e379 Mon Sep 17 00:00:00 2001 From: Mike Bayer Date: Thu, 29 Nov 2018 10:13:03 -0500 Subject: Allow optional *args with base AnsiFunction Amended the :class:`.AnsiFunction` class, the base of common SQL functions like ``CURRENT_TIMESTAMP``, to accept positional arguments like a regular ad-hoc function. This to suit the case that many of these functions on specific backends accept arguments such as "fractional seconds" precision and such. If the function is created with arguments, it renders the the parenthesis and the arguments. If no arguents are present, the compiler generates the non-parenthesized form. Fixes: #4386 Change-Id: Ic492ef177e4987cec99ec4d95f55292be8daa087 --- lib/sqlalchemy/sql/compiler.py | 17 +++++++++++------ lib/sqlalchemy/sql/functions.py | 15 +++++++++++---- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'lib/sqlalchemy/sql') diff --git a/lib/sqlalchemy/sql/compiler.py b/lib/sqlalchemy/sql/compiler.py index c2a23a758..80ed707ed 100644 --- a/lib/sqlalchemy/sql/compiler.py +++ b/lib/sqlalchemy/sql/compiler.py @@ -111,20 +111,20 @@ OPERATORS = { } FUNCTIONS = { - functions.coalesce: 'coalesce%(expr)s', + functions.coalesce: 'coalesce', functions.current_date: 'CURRENT_DATE', functions.current_time: 'CURRENT_TIME', functions.current_timestamp: 'CURRENT_TIMESTAMP', functions.current_user: 'CURRENT_USER', functions.localtime: 'LOCALTIME', functions.localtimestamp: 'LOCALTIMESTAMP', - functions.random: 'random%(expr)s', + functions.random: 'random', functions.sysdate: 'sysdate', functions.session_user: 'SESSION_USER', functions.user: 'USER', - functions.cube: 'CUBE%(expr)s', - functions.rollup: 'ROLLUP%(expr)s', - functions.grouping_sets: 'GROUPING SETS%(expr)s', + functions.cube: 'CUBE', + functions.rollup: 'ROLLUP', + functions.grouping_sets: 'GROUPING SETS', } EXTRACT_MAP = { @@ -927,7 +927,12 @@ class SQLCompiler(Compiled): if disp: return disp(func, **kwargs) else: - name = FUNCTIONS.get(func.__class__, func.name + "%(expr)s") + name = FUNCTIONS.get(func.__class__, None) + if name: + if func._has_args: + name += "%(expr)s" + else: + name = func.name + "%(expr)s" return ".".join(list(func.packagenames) + [name]) % \ {'expr': self.function_argspec(func, **kwargs)} diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index 5cea7750a..4b4d2d463 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -54,10 +54,13 @@ class FunctionElement(Executable, ColumnElement, FromClause): packagenames = () + _has_args = False + def __init__(self, *clauses, **kwargs): """Construct a :class:`.FunctionElement`. """ args = [_literal_as_binds(c, self.name) for c in clauses] + self._has_args = self._has_args or bool(args) self.clause_expr = ClauseList( operator=operators.comma_op, group_contents=True, *args).\ @@ -635,6 +638,7 @@ class GenericFunction(util.with_metaclass(_GenericMeta, Function)): parsed_args = kwargs.pop('_parsed_args', None) if parsed_args is None: parsed_args = [_literal_as_binds(c, self.name) for c in args] + self._has_args = self._has_args or bool(parsed_args) self.packagenames = [] self._bind = kwargs.get('bind', None) self.clause_expr = ClauseList( @@ -671,8 +675,8 @@ class next_value(GenericFunction): class AnsiFunction(GenericFunction): - def __init__(self, **kwargs): - GenericFunction.__init__(self, **kwargs) + def __init__(self, *args, **kwargs): + GenericFunction.__init__(self, *args, **kwargs) class ReturnTypeFromArgs(GenericFunction): @@ -686,7 +690,7 @@ class ReturnTypeFromArgs(GenericFunction): class coalesce(ReturnTypeFromArgs): - pass + _has_args = True class max(ReturnTypeFromArgs): @@ -717,7 +721,7 @@ class char_length(GenericFunction): class random(GenericFunction): - pass + _has_args = True class count(GenericFunction): @@ -937,6 +941,7 @@ class cube(GenericFunction): .. versionadded:: 1.2 """ + _has_args = True class rollup(GenericFunction): @@ -952,6 +957,7 @@ class rollup(GenericFunction): .. versionadded:: 1.2 """ + _has_args = True class grouping_sets(GenericFunction): @@ -984,3 +990,4 @@ class grouping_sets(GenericFunction): .. versionadded:: 1.2 """ + _has_args = True -- cgit v1.2.1