diff options
author | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-09-10 12:58:11 -0400 |
---|---|---|
committer | Mike Bayer <mike_mp@zzzcomputing.com> | 2012-09-10 12:58:11 -0400 |
commit | cd8b9dcd37e29b73a3c4b25adc16f1b45371fb7a (patch) | |
tree | f207c13c8a4cc11dceece70adec5e4c4ffe40bc8 /lib/sqlalchemy | |
parent | 15170b74d2f556499ae3f8d35c2d9bf5120b9ebd (diff) | |
download | sqlalchemy-cd8b9dcd37e29b73a3c4b25adc16f1b45371fb7a.tar.gz |
- [feature] The cast() and extract() constructs
will now be produced via the func.* accessor
as well, as users naturally try to access these
names from func.* they might as well do
what's expected, even though the returned
object is not a FunctionElement.
[ticket:2562]
Diffstat (limited to 'lib/sqlalchemy')
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 20 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/functions.py | 22 |
2 files changed, 31 insertions, 11 deletions
diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 7ef8e5b53..a817a2e5b 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -1268,7 +1268,7 @@ class _FunctionGenerator(object): func = _FunctionGenerator() """Generate SQL function expressions. - ``func`` is a special object instance which generates SQL + :data:`.func` is a special object instance which generates SQL functions based on name-based attributes, e.g.:: >>> print func.count(1) @@ -1280,7 +1280,7 @@ func = _FunctionGenerator() >>> print select([func.count(table.c.id)]) SELECT count(sometable.id) FROM sometable - Any name can be given to ``func``. If the function name is unknown to + Any name can be given to :data:`.func`. If the function name is unknown to SQLAlchemy, it will be rendered exactly as is. For common SQL functions which SQLAlchemy is aware of, the name may be interpreted as a *generic function* which will be compiled appropriately to the target database:: @@ -1304,7 +1304,8 @@ func = _FunctionGenerator() ... func.my_string(u'there', type_=Unicode) my_string(:my_string_1) || :my_string_2 || my_string(:my_string_3) - The object returned by a ``func`` call is an instance of :class:`.Function`. + The object returned by a :data:`.func` call is usually an instance of + :class:`.Function`. This object meets the "column" interface, including comparison and labeling functions. The object can also be passed the :meth:`~.Connectable.execute` method of a :class:`.Connection` or :class:`.Engine`, where it will be @@ -1312,12 +1313,15 @@ func = _FunctionGenerator() print connection.execute(func.current_timestamp()).scalar() - A function can also be "bound" to a :class:`.Engine` or :class:`.Connection` - using the ``bind`` keyword argument, providing an execute() as well - as a scalar() method:: + In a few exception cases, the :data:`.func` accessor + will redirect a name to a built-in expression such as :func:`.cast` + or :func:`.extract`, as these names have well-known meaning + but are not exactly the same as "functions" from a SQLAlchemy + perspective. - myfunc = func.current_timestamp(bind=some_engine) - print myfunc.scalar() + .. versionadded:: 0.8 :data:`.func` can return non-function expression + constructs for common quasi-functional names like :func:`.cast` + and :func:`.extract`. Functions which are interpreted as "generic" functions know how to calculate their return type automatically. For a listing of known generic diff --git a/lib/sqlalchemy/sql/functions.py b/lib/sqlalchemy/sql/functions.py index b24f8cbec..d26589bd9 100644 --- a/lib/sqlalchemy/sql/functions.py +++ b/lib/sqlalchemy/sql/functions.py @@ -6,7 +6,8 @@ from .. import types as sqltypes, schema from .expression import ( - ClauseList, Function, _literal_as_binds, literal_column, _type_from_args + ClauseList, Function, _literal_as_binds, literal_column, _type_from_args, + cast, extract ) from . import operators from .visitors import VisitableType @@ -14,6 +15,19 @@ from .. import util _registry = util.defaultdict(dict) +def register_function(identifier, fn, package="_default"): + """Associate a callable with a particular func. name. + + This is normally called by _GenericMeta, but is also + available by itself so that a non-Function construct + can be associated with the :data:`.func` accessor (i.e. + CAST, EXTRACT). + + """ + reg = _registry[package] + reg[identifier] = fn + + class _GenericMeta(VisitableType): def __init__(cls, clsname, bases, clsdict): cls.name = name = clsdict.get('name', clsname) @@ -22,8 +36,7 @@ class _GenericMeta(VisitableType): # legacy if '__return_type__' in clsdict: cls.type = clsdict['__return_type__'] - reg = _registry[package] - reg[identifier] = cls + register_function(identifier, cls, package) super(_GenericMeta, cls).__init__(clsname, bases, clsdict) class GenericFunction(Function): @@ -113,6 +126,9 @@ class GenericFunction(Function): kwargs.pop("type_", None) or getattr(self, 'type', None)) +register_function("cast", cast) +register_function("extract", extract) + class next_value(GenericFunction): """Represent the 'next value', given a :class:`.Sequence` as it's single argument. |