Visitor and Traversal Utilities
The sqlalchemy.sql.visitors
module consists of classes and functionsthat serve the purpose of generically traversing a Core SQL expressionstructure. This is not unlike the Python ast
module in that is presentsa system by which a program can operate upon each component of a SQLexpression. Common purposes this serves are locating various kinds ofelements such as Table
or BindParameter
objects,as well as altering the state of the structure such as replacing certain FROMclauses with others.
Note
the sqlalchemy.sql.visitors
module is an internal API andis not fully public. It is subject to change and may additionally notfunction as expected for use patterns that aren’t considered withinSQLAlchemy’s own internals.
The sqlalchemy.sql.visitors
module is part of the internals ofSQLAlchemy and it is not usually used by calling application code. It ishowever used in certain edge cases such as when constructing caching routinesas well as when building out custom SQL expressions using theCustom SQL Constructs and Compilation Extension.
Visitor/traversal interface and library functions.
SQLAlchemy schema and expression constructs rely on a Python-centricversion of the classic “visitor” pattern as the primary way in whichthey apply functionality. The most common use of this patternis statement compilation, where individual expression classes matchup to rendering methods that produce a string result. Beyond this,the visitor system is also used to inspect expressions for variousinformation and patterns, as well as for the purposes of applyingtransformations to expressions.
Examples of how the visit system is used can be seen in the source codeof for example the sqlalchemy.sql.util
and the sqlalchemy.sql.compiler
modules. Some background on clause adaption is also athttp://techspot.zzzeek.org/2008/01/23/expression-transformations/ .
Metaclass which assigns a compilerdispatch
method to classeshaving a __visit_name
attribute.
The _compiler_dispatch
attribute becomes an instance method whichlooks approximately like the following:
- def _compiler_dispatch (self, visitor, **kw):
- '''Look for an attribute named "visit_" + self.__visit_name__
- on the visitor, and call it with the same kw params.'''
- visit_attr = 'visit_%s' % self.__visit_name__
- return getattr(visitor, visit_attr)(self, **kw)
Classes having no visit_name
attribute will remain unaffected.
- class
sqlalchemy.sql.visitors.
Visitable
- Base class for visitable objects, applies the
visitors.VisitableType
metaclass.
The Visitable
class is essentially at the base of theClauseElement
hierarchy.
- class
sqlalchemy.sql.visitors.
ClauseVisitor
- Base class for visitor objects which can traverse usingthe
visitors.traverse()
function.
Direct usage of the visitors.traverse()
function is usuallypreferred.
the chained visitor will receive all visit events after this one.
iterate
(obj)traverse the given expression structure, returning an iteratorof all elements.
traverse and visit the given expression structure.
- iterate through this visitor and each ‘chained’ visitor.
- class
sqlalchemy.sql.visitors.
CloningVisitor
- Bases:
sqlalchemy.sql.visitors.ClauseVisitor
Base class for visitor objects which can traverse usingthe visitors.cloned_traverse()
function.
Direct usage of the visitors.cloned_traverse()
function is usuallypreferred.
copyandprocess
(_list)Apply cloned traversal to the given list of elements, and returnthe new list.
- traverse and visit the given expression structure.
- class
sqlalchemy.sql.visitors.
ReplacingCloningVisitor
- Bases:
sqlalchemy.sql.visitors.CloningVisitor
Base class for visitor objects which can traverse usingthe visitors.replacement_traverse()
function.
Direct usage of the visitors.replacement_traverse()
function isusually preferred.
If the method returns a new element, the element is usedinstead of creating a simple copy of the element. Traversalwill halt on the newly returned element if it is re-encountered.
sqlalchemy.sql.visitors.
iterate
(obj, opts)- traverse the given expression structure, returning an iterator.
traversal is configured to be breadth-first.
The central API feature used by the visitors.iterate()
andvisitors.iterate_depthfirst()
functions is theClauseElement.get_children()
method of ClauseElement
objects. This method should return all the ClauseElement
objectswhich are associated with a particular ClauseElement
object.For example, a Case
structure will refer to a series ofColumnElement
objects within its “whens” and “else_” membervariables.
- Parameters
obj –
ClauseElement
structure to be traversedopts – dictionary of iteration options. This dictionary is usuallyempty in modern usage.
sqlalchemy.sql.visitors.
iteratedepthfirst
(_obj, opts)- traverse the given expression structure, returning an iterator.
traversal is configured to be depth-first.
- Parameters
obj –
ClauseElement
structure to be traversedopts – dictionary of iteration options. This dictionary is usuallyempty in modern usage.
See also
visitors.iterate()
- includes a general overview of iteration.
sqlalchemy.sql.visitors.
traverseusing
(_iterator, obj, visitors)- visit the given expression structure using the given iterator ofobjects.
visitors.traverse_using()
is usually called internally as the resultof the visitors.traverse()
or visitors.traverse_depthfirst()
functions.
- Parameters
iterator – an iterable or sequence which will yield
ClauseElement
structures; the iterator is assumed to be theproduct of thevisitors.iterate()
orvisitors.iterate_depthfirst()
functions.obj – the
ClauseElement
that was used as the target of theiterate()
oriterate_depthfirst()
function.visitors – dictionary of visit functions. See
traverse()
for details on this dictionary.
See also
sqlalchemy.sql.visitors.
traverse
(obj, opts, visitors)- traverse and visit the given expression structure using the defaultiterator.
e.g.:
- from sqlalchemy.sql import visitorsstmt = select([some_table]).where(some_table.c.foo == 'bar')def visit_bindparam(bind_param): print("found bound value: %s" % bind_param.value)visitors.traverse(stmt, {}, {"bindparam": visit_bindparam})
The iteration of objects uses the visitors.iterate()
function,which does a breadth-first traversal using a stack.
- Parameters
obj –
ClauseElement
structure to be traversedopts – dictionary of iteration options. This dictionary is usuallyempty in modern usage.
visitors – dictionary of visit functions. The dictionary shouldhave strings as keys, each of which would correspond to the
visit_name
of a particular kind of SQL expression object, andcallable functions as values, each of which represents a visitor functionfor that kind of object.
sqlalchemy.sql.visitors.
traversedepthfirst
(_obj, opts, visitors)- traverse and visit the given expression structure using thedepth-first iterator.
The iteration of objects uses the visitors.iterate_depthfirst()
function, which does a depth-first traversal using a stack.
Usage is the same as that of visitors.traverse()
function.
sqlalchemy.sql.visitors.
clonedtraverse
(_obj, opts, visitors)- clone the given expression structure, allowing modifications byvisitors.
Traversal usage is the same as that of visitors.traverse()
.The visitor functions present in the visitors
dictionary may alsomodify the internals of the given structure as the traversal proceeds.
The central API feature used by the visitors.cloned_traverse()
and visitors.replacement_traverse()
functions, in addition to theClauseElement.get_children()
function that is used to achievethe iteration, is the ClauseElement._copy_internals()
method.For a ClauseElement
structure to support cloning and replacementtraversals correctly, it needs to be able to pass a cloning function intoits internal members in order to make copies of them.
See also
visitors.replacement_traverse()
sqlalchemy.sql.visitors.
replacementtraverse
(_obj, opts, replace)- clone the given expression structure, allowing elementreplacement by a given replacement function.
This function is very similar to the visitors.cloned_traverse()
function, except instead of being passed a dictionary of visitors, allelements are unconditionally passed into the given replace function.The replace function then has the option to return an entirely new objectwhich will replace the one given. if it returns None
, then the objectis kept in place.
The difference in usage between visitors.cloned_traverse()
andvisitors.replacement_traverse()
is that in the former case, analready-cloned object is passed to the visitor function, and the visitorfunction can then manipulate the internal state of the object.In the case of the latter, the visitor function should only return anentirely different object, or do nothing.
The use case for visitors.replacement_traverse()
is that ofreplacing a FROM clause inside of a SQL structure with a different one,as is a common use case within the ORM.