diff options
-rw-r--r-- | doc/build/core/expression_api.rst | 4 | ||||
-rw-r--r-- | doc/build/core/types.rst | 49 | ||||
-rw-r--r-- | doc/build/index.rst | 2 | ||||
-rw-r--r-- | lib/sqlalchemy/sql/expression.py | 16 | ||||
-rw-r--r-- | lib/sqlalchemy/types.py | 51 |
5 files changed, 57 insertions, 65 deletions
diff --git a/doc/build/core/expression_api.rst b/doc/build/core/expression_api.rst index 66338efae..7797e9d7a 100644 --- a/doc/build/core/expression_api.rst +++ b/doc/build/core/expression_api.rst @@ -200,6 +200,10 @@ Classes :members: :show-inheritance: +.. autoclass:: UnaryExpression + :members: + :show-inheritance: + .. autoclass:: Update :members: :show-inheritance: diff --git a/doc/build/core/types.rst b/doc/build/core/types.rst index 9a7ff3414..2838b722f 100644 --- a/doc/build/core/types.rst +++ b/doc/build/core/types.rst @@ -661,23 +661,50 @@ we create a :class:`.Integer` subclass which overrides the :meth:`.ColumnOperato The above configuration creates a new class ``MyInt``, which establishes the :attr:`.TypeEngine.comparator_factory` attribute as -referring to a new class, subclassing the ``Comparator`` class +referring to a new class, subclassing the :class:`.TypeEngine.Comparator` class associated with the :class:`.Integer` type. +Usage:: + + >>> sometable = Table("sometable", metadata, Column("data", MyInt)) + >>> print sometable.c.data + 5 + sometable.data goofy :data_1 + The implementation for :meth:`.ColumnOperators.__add__` is consulted -by an owning SQL expression, by instantiating the ``Comparator`` with +by an owning SQL expression, by instantiating the :class:`.TypeEngine.Comparator` with itself as as the ``expr`` attribute. The mechanics of the expression system are such that operations continue recursively until an expression object produces a new SQL expression construct. Above, we could just as well have said ``self.expr.op("goofy")(other)`` instead of ``self.op("goofy")(other)``. -New methods added to a ``Comparator`` are exposed on an owning SQL expression -using a ``__getattr__`` scheme. For example, to add an implementation of the -Postgresql factorial operator:: +New methods added to a :class:`.TypeEngine.Comparator` are exposed on an +owning SQL expression +using a ``__getattr__`` scheme, which exposes methods added to +:class:`.TypeEngine.Comparator` onto the owning :class:`.ColumnElement`. +For example, to add a ``log()`` function +to integers:: + + from sqlalchemy import Integer, func + + class MyInt(Integer): + class comparator_factory(Integer.Comparator): + def log(self, other): + return func.log(self, other) + +Using the above type:: + + >>> print sometable.c.data.log(5) + log(:log_1, :log_2) + + +Unary operations +are also possible. For example, to add an implementation of the +Postgresql factorial operator, we combine the :class:`.UnaryExpression` construct +along with a :class:`.custom_op` to produce the factorial expression:: from sqlalchemy import Integer - from sqlalchemy.sql import UnaryExpression + from sqlalchemy.sql.expression import UnaryExpression from sqlalchemy.sql import operators class MyInteger(Integer): @@ -687,6 +714,16 @@ Postgresql factorial operator:: modifier=operators.custom_op("!"), type_=MyInteger) +Using the above type:: + + >>> from sqlalchemy.sql import column + >>> print column('x', MyInteger).factorial() + x ! + +See also: + +:attr:`.TypeEngine.comparator_factory` + .. versionadded:: 0.8 The expression system was enhanced to support customization of operators on a per-type level. diff --git a/doc/build/index.rst b/doc/build/index.rst index 48e558af2..ada12bcc6 100644 --- a/doc/build/index.rst +++ b/doc/build/index.rst @@ -84,6 +84,7 @@ are documented here. In contrast to the ORM's domain-centric mode of usage, the :ref:`SQL Standard Types <types_sqlstandard>` | :ref:`Vendor Specific Types <types_vendor>` | :ref:`Building Custom Types <types_custom>` | + :ref:`Defining New Operators <types_operators>` | :ref:`API <types_api>` * **Extending the Core:** @@ -94,7 +95,6 @@ are documented here. In contrast to the ORM's domain-centric mode of usage, the * **Other:** :doc:`Runtime Inspection API <core/inspection>` | - :doc:`Serializing Expressions <core/serializer>` | :doc:`core/interfaces` | :doc:`core/exceptions` diff --git a/lib/sqlalchemy/sql/expression.py b/lib/sqlalchemy/sql/expression.py index 969a6920b..0974b7e50 100644 --- a/lib/sqlalchemy/sql/expression.py +++ b/lib/sqlalchemy/sql/expression.py @@ -2141,21 +2141,21 @@ class _DefaultColumnComparator(operators.ColumnOperators): class ColumnElement(ClauseElement, ColumnOperators): - """Represent an element that is usable within the "column clause" portion - of a ``SELECT`` statement. + """Represent a column-oriented SQL expression suitable for usage in the + "columns" clause, WHERE clause etc. of a statement. While the most familiar kind of :class:`.ColumnElement` is the :class:`.Column` object, :class:`.ColumnElement` serves as the basis for any unit that may be present in a SQL expression, including - the columns associated with tables, aliases, and - subqueries, expressions, function calls, SQL keywords such as - ``NULL``, literals, etc. :class:`.ColumnElement` is the ultimate base - class for all such elements. + the expressions themselves, SQL functions, bound parameters, + literal expressions, keywords such as ``NULL``, etc. :class:`.ColumnElement` + is the ultimate base class for all such elements. - A :class:`.ColumnElement` provides the ability to generate new :class:`.ClauseElement` + A :class:`.ColumnElement` provides the ability to generate new + :class:`.ColumnElement` objects using Python expressions. This means that Python operators such as ``==``, ``!=`` and ``<`` are overloaded to mimic SQL operations, - and allow the construction of :class:`.ColumnElement` constructs which + and allow the instantiation of further :class:`.ColumnElement` instances which are composed from other, more fundamental :class:`.ColumnElement` objects. For example, two :class:`.ColumnClause` objects can be added together with the addition operator ``+`` to produce diff --git a/lib/sqlalchemy/types.py b/lib/sqlalchemy/types.py index 6c936fa3e..a082daf63 100644 --- a/lib/sqlalchemy/types.py +++ b/lib/sqlalchemy/types.py @@ -74,56 +74,7 @@ class TypeEngine(AbstractType): Rudimentary usage of this hook is allowed through simple subclassing of existing types, or alternatively by using :class:`.TypeDecorator`. - E.g. to overload the ``+`` operator on :class:`.Integer`:: - - from sqlalchemy import Integer - - class MyInt(Integer): - class comparator_factory(Integer.Comparator): - def __add__(self, other): - return self.op("goofy")(other) - - Usage:: - - >>> sometable = Table("sometable", metadata, Column("data", MyInt)) - >>> print sometable.c.data + 5 - sometable.data goofy :data_1 - - New comparison methods and operations applied to :class:`.TypeEngine.Comparator` - are made available on parent SQL constructs using a ``__getattr__()`` scheme:: - - from sqlalchemy import Integer, func - - class MyInt(Integer): - class comparator_factory(Integer.Comparator): - def log(self, other): - return func.log(self, other) - - E.g.:: - - >>> print sometable.c.data.log(5) - log(:log_1, :log_2) - - The :class:`.TypeEngine` associated with a particular :class:`.ColumnElement` - is propagated during expression construction to the containing elements - according to simple "adaptation" rules. An example of an "adaptation" - would be adding two integers leads to a "binary" expression that is also - of type integer:: - - >>> from sqlalchemy.sql import column - >>> from sqlalchemy.types import Integer - >>> c1 = column('c1', Integer) - >>> c2 = column('c2', Integer) - >>> c1.type - Integer() - >>> (c1 + c2).type - Integer() - - If the two columns above were compared using a boolean operator, - the resulting type would instead be :class:`.Boolean`:: - - >>> (c1 == c2).type - Boolean() + See the documentation section :ref:`types_operators` for examples. .. versionadded:: 0.8 The expression system was enhanced to support customization of operators on a per-type level. |