import docstring
import re
-from sqlalchemy import schema, types, engine, sql, pool, orm, exceptions, databases, interfaces
-from sqlalchemy.sql import compiler, expression
+from sqlalchemy import schema, types, engine, sql, pool, orm, exceptions, databases, interfaces, util
+from sqlalchemy.sql import compiler, expression, visitors
from sqlalchemy.engine import default, strategies, threadlocal, url
from sqlalchemy.orm import shard
from sqlalchemy.ext import orderinglist, associationproxy, sqlsoup, declarative, serializer
make_doc(obj=interfaces),
make_doc(obj=pool),
make_doc(obj=schema),
- #make_doc(obj=sql,include_all_classes=True),
make_doc(obj=compiler),
- make_doc(obj=expression,include_all_classes=True),
+ make_doc(obj=expression,
+ classes=[getattr(expression, key) for key in expression.__all__ if isinstance(getattr(expression, key), type)] +
+ [expression._CompareMixin, expression.Operators, expression.ColumnOperators,
+ expression._SelectBaseMixin, expression._Immutable, expression._ValuesBase, expression._UpdateBase]
+ ),
+ make_doc(obj=visitors),
make_doc(obj=types),
+ make_doc(obj=util),
make_doc(obj=orm),
make_doc(obj=orm.attributes),
make_doc(obj=orm.collections, classes=[orm.collections.collection,
intersect,
intersect_all,
join,
+ label,
literal,
literal_column,
modifier,
'between', 'bindparam', 'case', 'cast', 'column', 'delete',
'desc', 'distinct', 'except_', 'except_all', 'exists', 'extract', 'func',
'modifier', 'collate',
- 'insert', 'intersect', 'intersect_all', 'join', 'literal',
+ 'insert', 'intersect', 'intersect_all', 'join', 'label', 'literal',
'literal_column', 'not_', 'null', 'or_', 'outparam', 'outerjoin', 'select',
'subquery', 'table', 'text', 'union', 'union_all', 'update', ]
def compile(self, bind=None, column_keys=None, compiler=None, dialect=None, inline=False):
"""Compile this SQL expression.
-
- Uses the given ``Compiler``, or the given ``AbstractDialect``
- or ``Engine`` to create a ``Compiler``. If no `compiler`
- arguments are given, tries to use the underlying ``Engine``
- this ``ClauseElement`` is bound to to create a ``Compiler``,
- if any.
-
- Finally, if there is no bound ``Engine``, uses an
- ``DefaultDialect`` to create a default ``Compiler``.
-
- `parameters` is a dictionary representing the default bind
- parameters to be used with the statement. If `parameters` is
- a list, it is assumed to be a list of dictionaries and the
- first dictionary in the list is used with which to compile
- against.
-
- The bind parameters can in some cases determine the output of
- the compilation, such as for ``UPDATE`` and ``INSERT``
- statements the bind parameters that are present determine the
- ``SET`` and ``VALUES`` clause of those statements.
+
+ The return value is a [sqlalchemy.engine#Compiled] object.
+ Calling `str()` or `unicode()` on the returned value will yield
+ a string representation of the result. The ``Compiled``
+ object also can return a dictionary of bind parameter names and
+ values using the `params` accessor.
+
+ bind
+ An ``Engine`` or ``Connection`` from which a
+ ``Compiled`` will be acquired. This argument
+ takes precedence over this ``ClauseElement``'s
+ bound engine, if any.
+
+ column_keys
+ Used for INSERT and UPDATE statements, a list of
+ column names which should be present in the VALUES clause
+ of the compiled statement. If ``None``, all columns
+ from the target table object are rendered.
+
+ compiler
+ A ``Compiled`` instance which will be used to compile
+ this expression. This argument takes precedence
+ over the `bind` and `dialect` arguments as well as
+ this ``ClauseElement``'s bound engine, if
+ any.
+
+ dialect
+ A ``Dialect`` instance frmo which a ``Compiled``
+ will be acquired. This argument takes precedence
+ over the `bind` argument as well as this
+ ``ClauseElement``'s bound engine, if any.
+
+ inline
+ Used for INSERT statements, for a dialect which does
+ not support inline retrieval of newly generated
+ primary key columns, will force the expression used
+ to create the new primary key value to be rendered
+ inline within the INSERT statement's VALUES clause.
+ This typically refers to Sequence execution but
+ may also refer to any server-side default generation
+ function associated with a primary key `Column`.
"""
if compiler is None:
compiler = bind.statement_compiler(self, column_keys=column_keys, inline=inline)
elif self.bind is not None:
compiler = self.bind.statement_compiler(self, column_keys=column_keys, inline=inline)
-
- if compiler is None:
- global DefaultDialect
- if DefaultDialect is None:
- from sqlalchemy.engine.default import DefaultDialect
- dialect = DefaultDialect()
- compiler = dialect.statement_compiler(dialect, self, column_keys=column_keys, inline=inline)
+ else:
+ global DefaultDialect
+ if DefaultDialect is None:
+ from sqlalchemy.engine.default import DefaultDialect
+ dialect = DefaultDialect()
+ compiler = dialect.statement_compiler(dialect, self, column_keys=column_keys, inline=inline)
compiler.compile()
return compiler
@util.memoized_property
def type(self):
- return sqltypes.to_instance(self._type or getattr(element, 'type', None))
+ return sqltypes.to_instance(self._type or getattr(self._element, 'type', None))
@util.memoized_property
def element(self):
+"""Visitor/traversal interface and library functions.
+
+SQLAlchemy schema and expression constructs rely on a Python-centric
+version of the classic "visitor" pattern as the primary way in which
+they apply functionality. The most common use of this pattern
+is statement compilation, where individual expression classes match
+up to rendering methods that produce a string result. Beyond this,
+the visitor system is also used to inspect expressions for various
+information and patterns, as well as for usage in
+some kinds of expression transformation. Other kinds of transformation
+use a non-visitor traversal system.
+
+For many examples of how the visit system is used, see the
+sqlalchemy.sql.util and the sqlalchemy.sql.compiler modules.
+For an introduction to clause adaption, see
+http://techspot.zzzeek.org/?p=19 .
+
+"""
+
from collections import deque
import re
from sqlalchemy import util
+__all__ = ['VisitableType', 'Visitable', 'ClauseVisitor',
+ 'CloningVisitor', 'ReplacingCloningVisitor', 'iterate',
+ 'iterate_depthfirst', 'traverse_using', 'traverse',
+ 'cloned_traverse', 'replacement_traverse']
+
class VisitableType(type):
+ """Metaclass which applies a `__visit_name__` attribute and
+ `_compiler_dispatch` method to classes.
+
+ """
+
def __init__(cls, clsname, bases, dict):
if not '__visit_name__' in cls.__dict__:
m = re.match(r'_?(\w+?)(?:Expression|Clause|Element|$)', clsname)
super(VisitableType, cls).__init__(clsname, bases, dict)
class Visitable(object):
+ """Base class for visitable objects, applies the
+ ``VisitableType`` metaclass.
+
+ """
+
__metaclass__ = VisitableType
class ClauseVisitor(object):
+ """Base class for visitor objects which can traverse using
+ the traverse() function.
+
+ """
+
__traverse_options__ = {}
def traverse_single(self, obj):
return self
class CloningVisitor(ClauseVisitor):
+ """Base class for visitor objects which can traverse using
+ the cloned_traverse() function.
+
+ """
+
def copy_and_process(self, list_):
"""Apply cloned traversal to the given list of elements, and return the new list."""
return cloned_traverse(obj, self.__traverse_options__, self._visitor_dict)
class ReplacingCloningVisitor(CloningVisitor):
+ """Base class for visitor objects which can traverse using
+ the replacement_traverse() function.
+
+ """
+
def replace(self, elem):
"""receive pre-copied elements during a cloning traversal.
return traverse_using(iterate_depthfirst(obj, opts), obj, visitors)
def cloned_traverse(obj, opts, visitors):
+ """clone the given expression structure, allowing modifications by visitors."""
+
cloned = {}
def clone(element):
return obj
def replacement_traverse(obj, opts, replace):
+ """clone the given expression structure, allowing element replacement by a given replacement function."""
+
cloned = {}
stop_on = set(opts.get('stop_on', []))
"""Return the full set of inherited kwargs for the given `cls`.
Probes a class's __init__ method, collecting all named arguments. If the
- __init__ defines a **kwargs catch-all, then the constructor is presumed to
+ __init__ defines a \**kwargs catch-all, then the constructor is presumed to
pass along unrecognized keywords to it's base classes, and the collection
process is repeated recursively on each of the bases.
+
"""
for c in cls.__mro__:
return bool(obj)
def coerce_kw_type(kw, key, type_, flexi_bool=True):
- """If 'key' is present in dict 'kw', coerce its value to type 'type_' if
+ """If 'key' is present in dict 'kw', coerce its value to type 'type\_' if
necessary. If 'flexi_bool' is True, the string '0' is considered false
when coercing to boolean.
"""
import datetime, re, operator
from sqlalchemy import *
from sqlalchemy import exc, sql, util
-from sqlalchemy.sql import table, column, compiler
+from sqlalchemy.sql import table, column, label, compiler
from sqlalchemy.engine import default
from sqlalchemy.databases import sqlite, postgres, mysql, oracle, firebird, mssql
from testlib import *
x = func.lala(table1.c.myid).label('foo')
self.assert_compile(select([x], x==5), "SELECT lala(mytable.myid) AS foo FROM mytable WHERE lala(mytable.myid) = :param_1")
+ self.assert_compile(label('bar', column('foo', type_=String)) + "foo", "foo || :param_1")
def test_conjunctions(self):