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.compilermodules. Some background on clause adaption is also athttp://techspot.zzzeek.org/2008/01/23/expression-transformations/ .

  • class sqlalchemy.sql.visitors.VisitableType(clsname, bases, clsdict)
  • Bases: builtins.type

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:

  1. def _compiler_dispatch (self, visitor, **kw):
  2. '''Look for an attribute named "visit_" + self.__visit_name__
  3. on the visitor, and call it with the same kw params.'''
  4. visit_attr = 'visit_%s' % self.__visit_name__
  5. 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 thevisitors.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.

  • chain(visitor)
  • ‘chain’ an additional ClauseVisitor onto this ClauseVisitor.

the chained visitor will receive all visit events after this one.

  • iterate(obj)
  • traverse the given expression structure, returning an iteratorof all elements.

  • traverse(obj)

  • traverse and visit the given expression structure.

  • property visitor_iterator

  • iterate through this visitor and each ‘chained’ visitor.

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(obj)

  • traverse and visit the given expression structure.

Base class for visitor objects which can traverse usingthe visitors.replacement_traverse() function.

Direct usage of the visitors.replacement_traverse() function isusually preferred.

  • replace(elem)
  • receive pre-copied elements during a cloning traversal.

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.

  • traverse(obj)
  • traverse and visit the given expression structure.
  • 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 ClauseElementobjects. 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
    • objClauseElement structure to be traversed

    • opts – 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
    • objClauseElement structure to be traversed

    • opts – 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.

See also

traverse()

traverse_depthfirst()

  • sqlalchemy.sql.visitors.traverse(obj, opts, visitors)
  • traverse and visit the given expression structure using the defaultiterator.

e.g.:

  1. 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
    • objClauseElement structure to be traversed

    • opts – 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 thevisit_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.traverse()

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.