]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
- fixed prefixes= argument to select()
authorJason Kirtland <jek@discorporate.us>
Sat, 18 Aug 2007 18:15:11 +0000 (18:15 +0000)
committerJason Kirtland <jek@discorporate.us>
Sat, 18 Aug 2007 18:15:11 +0000 (18:15 +0000)
- mysql can now generate DISTINCT or ALL for queries, select(..., distinct='ALL')
- documented 'prefixes' arg to select()
- rearranged doc order for select args to mirror that of a generated statement
- went nutty and fixed wrapping and line length on most docstrings in sql.py

CHANGES
lib/sqlalchemy/databases/mysql.py
lib/sqlalchemy/sql.py
test/dialect/mysql.py

diff --git a/CHANGES b/CHANGES
index b52de26136af8f18f76ffb9d337bc9fd8cfc572d..9e9aff6d036640eeaa42ab43e2ba503b1719db10 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -9,26 +9,30 @@ CHANGES
   still get processed/encoded.
 
 - Added a "legacy" adapter to types, such that user-defined TypeEngine
-  and TypeDecorator classes which define convert_bind_param()/convert_result_value()
-  will continue to function.  Also supports calling the super() version of
-  those methods.
+  and TypeDecorator classes which define convert_bind_param() and/or
+  convert_result_value() will continue to function.  Also supports
+  calling the super() version of those methods.
   
-- Added session.prune(), trims away instances cached in a session that are no
-  longer referenced elsewhere. (A utility for strong-ref identity maps).
+- Added session.prune(), trims away instances cached in a session that
+  are no longer referenced elsewhere. (A utility for strong-ref
+  identity maps).
 
-- added close() method to Transaction.  closes out a transaction using rollback
-  if it's the outermost transaction, otherwise just ends without affecting
-  the outer transaction.
+- Added close() method to Transaction.  Closes out a transaction using
+  rollback if it's the outermost transaction, otherwise just ends
+  without affecting the outer transaction.
 
-- transactional and non-transactional Session integrates better with bound 
-  connection; a close() will ensure that connection transactional state is 
-  the same as that which existed on it before being bound to the Session.
+- Transactional and non-transactional Session integrates better with
+  bound connection; a close() will ensure that connection
+  transactional state is the same as that which existed on it before
+  being bound to the Session.
 
-- modified SQL operator functions to be module-level operators, allowing
-  SQL expressions to be pickleable [ticket:735]
+- Modified SQL operator functions to be module-level operators,
+  allowing SQL expressions to be pickleable. [ticket:735]
 
-- small adjustment to mapper class.__init__ to allow for Py2.6 object.__init__()
-  behavior
+- Small adjustment to mapper class.__init__ to allow for Py2.6
+  object.__init__() behavior.
+
+- Fixed 'prefix' argument for select()
     
 0.4.0beta3
 ----------
index 303a445525e691efa8770ed431754f70e84e31b0..d5fd3b6c53047e1e000a877ce52877f93c006ff8 100644 (file)
@@ -1752,6 +1752,14 @@ class MySQLCompiler(ansisql.ANSICompiler):
             # TODO: put whatever MySQL does for CAST here.
             return self.process(cast.clause)
 
+    def get_select_precolumns(self, select):
+        if isinstance(select._distinct, basestring):
+            return select._distinct.upper() + " "
+        elif select._distinct:
+            return "DISTINCT "
+        else:
+            return ""
+
     def for_update_clause(self, select):
         if select.for_update == 'read':
              return ' LOCK IN SHARE MODE'
index 2f1cd4b91a89206c3b572b0fc802cd4d04090b61..7c73f7cb7ff2b0fc853c5119406db5b68d9cdc34 100644 (file)
@@ -4,46 +4,50 @@
 # This module is part of SQLAlchemy and is released under
 # the MIT License: http://www.opensource.org/licenses/mit-license.php
 
-"""Define the base components of SQL expression trees.
-
-All components are derived from a common base class [sqlalchemy.sql#ClauseElement].
-Common behaviors are organized based on class hierarchies, in some cases
-via mixins.  
-
-All object construction from this package occurs via functions which in some
-cases will construct composite ``ClauseElement`` structures together, and
-in other cases simply return a single ``ClauseElement`` constructed directly.
-The function interface affords a more "DSL-ish" feel to constructing SQL expressions
-and also allows future class reorganizations.
-
-Even though classes are not constructed directly from the outside, most 
-classes which have additional public methods are considered to be public (i.e. have no leading underscore).
-Other classes which are "semi-public" are marked with a single leading
-underscore; these classes usually have few or no public methods and
-are less guaranteed to stay the same in future releases.
-
+"""Defines the base components of SQL expression trees.
+
+
+All components are derived from a common base class
+[sqlalchemy.sql#ClauseElement].  Common behaviors are organized based
+on class hierarchies, in some cases via mixins.
+
+All object construction from this package occurs via functions which
+in some cases will construct composite ``ClauseElement`` structures
+together, and in other cases simply return a single ``ClauseElement``
+constructed directly.  The function interface affords a more "DSL-ish"
+feel to constructing SQL expressions and also allows future class
+reorganizations.
+
+Even though classes are not constructed directly from the outside,
+most classes which have additional public methods are considered to be
+public (i.e. have no leading underscore).  Other classes which are
+"semi-public" are marked with a single leading underscore; these
+classes usually have few or no public methods and are less guaranteed
+to stay the same in future releases.
 """
 
 from sqlalchemy import util, exceptions, operators
 from sqlalchemy import types as sqltypes
 import re
 
-__all__ = ['Alias', 'ClauseElement', 'ClauseParameters',
-           'ClauseVisitor', 'ColumnCollection', 'ColumnElement',
-           'CompoundSelect', 'Delete', 'FromClause', 'Insert', 'Join', 
-           'Select', 'Selectable', 'TableClause', 'Update', 'alias', 'and_', 'asc',
-           'between', 'bindparam', 'case', 'cast', 'column', 'delete',
-           'desc', 'distinct', 'except_', 'except_all', 'exists', 'extract', 'func', 'modifier',
-           'insert', 'intersect', 'intersect_all', 'join', 'literal',
-           'literal_column', 'not_', 'null', 'or_', 'outparam', 'outerjoin', 'select',
-           'subquery', 'table', 'text', 'union', 'union_all', 'update',]
+__all__ = [
+    'Alias', 'ClauseElement', 'ClauseParameters',
+    'ClauseVisitor', 'ColumnCollection', 'ColumnElement',
+    'CompoundSelect', 'Delete', 'FromClause', 'Insert', 'Join',
+    'Select', 'Selectable', 'TableClause', 'Update', 'alias', 'and_', 'asc',
+    'between', 'bindparam', 'case', 'cast', 'column', 'delete',
+    'desc', 'distinct', 'except_', 'except_all', 'exists', 'extract', 'func',
+    'modifier',
+    'insert', 'intersect', 'intersect_all', 'join', 'literal',
+    'literal_column', 'not_', 'null', 'or_', 'outparam', 'outerjoin', 'select',
+    'subquery', 'table', 'text', 'union', 'union_all', 'update', ]
 
 BIND_PARAMS = re.compile(r'(?<![:\w\x5c]):(\w+)(?!:)', re.UNICODE)
 
 def desc(column):
     """Return a descending ``ORDER BY`` clause element.
 
-    E.g.::
+    e.g.::
 
       order_by = [desc(table1.mycol)]
     """
@@ -52,7 +56,7 @@ def desc(column):
 def asc(column):
     """Return an ascending ``ORDER BY`` clause element.
 
-    E.g.::
+    e.g.::
 
       order_by = [asc(table1.mycol)]
     """
@@ -60,22 +64,22 @@ def asc(column):
 
 def outerjoin(left, right, onclause=None, **kwargs):
     """Return an ``OUTER JOIN`` clause element.
-    
+
     The returned object is an instance of [sqlalchemy.sql#Join].
 
-    Similar functionality is also available via the ``outerjoin()`` method on any
-    [sqlalchemy.sql#FromClause].
+    Similar functionality is also available via the ``outerjoin()``
+    method on any [sqlalchemy.sql#FromClause].
 
-      left
-        The left side of the join.
+    left
+      The left side of the join.
 
-      right
-        The right side of the join.
+    right
+      The right side of the join.
 
-      onclause
-        Optional criterion for the ``ON`` clause, is derived from
-        foreign key relationships established between left and right
-        otherwise.
+    onclause
+      Optional criterion for the ``ON`` clause, is derived from
+      foreign key relationships established between left and right
+      otherwise.
 
     To chain joins together, use the ``join()`` or ``outerjoin()``
     methods on the resulting ``Join`` object.
@@ -88,19 +92,19 @@ def join(left, right, onclause=None, **kwargs):
 
     The returned object is an instance of [sqlalchemy.sql#Join].
 
-    Similar functionality is also available via the ``join()`` method on any
-    [sqlalchemy.sql#FromClause].
+    Similar functionality is also available via the ``join()`` method
+    on any [sqlalchemy.sql#FromClause].
 
-      left
-        The left side of the join.
+    left
+      The left side of the join.
 
-      right
-        The right side of the join.
+    right
+      The right side of the join.
 
-      onclause
-        Optional criterion for the ``ON`` clause, is derived from
-        foreign key relationships established between left and right
-        otherwise.
+    onclause
+      Optional criterion for the ``ON`` clause, is derived from
+      foreign key relationships established between left and right
+      otherwise.
 
     To chain joins together, use the ``join()`` or ``outerjoin()``
     methods on the resulting ``Join`` object.
@@ -111,109 +115,116 @@ def join(left, right, onclause=None, **kwargs):
 def select(columns=None, whereclause=None, from_obj=[], **kwargs):
     """Returns a ``SELECT`` clause element.
 
-    Similar functionality is also available via the ``select()`` method on any
-    [sqlalchemy.sql#FromClause].
-    
+    Similar functionality is also available via the ``select()``
+    method on any [sqlalchemy.sql#FromClause].
+
     The returned object is an instance of [sqlalchemy.sql#Select].
 
-    All arguments which accept ``ClauseElement`` arguments also
-    accept string arguments, which will be converted as appropriate
-    into either ``text()`` or ``literal_column()`` constructs.
-    
-      columns
-        A list of ``ClauseElement`` objects, typically ``ColumnElement``
-        objects or subclasses, which will form
-        the columns clause of the resulting statement.  For all
-        members which are instances of ``Selectable``, the individual
-        ``ColumnElement`` members of the ``Selectable`` will be 
-        added individually to the columns clause.  For example, specifying
-        a ``Table`` instance will result in all the contained ``Column``
-        objects within to be added to the columns clause. 
-    
-        This argument is not present on the form of ``select()`` available
-        on ``Table``.
-      
-      whereclause
-        A ``ClauseElement`` expression which will be used to form the 
-        ``WHERE`` clause.
-      
-      from_obj
-        A list of ``ClauseElement`` objects which will be added to the ``FROM``
-        clause of the resulting statement.  Note that "from" objects
-        are automatically located within the columns and whereclause
-        ClauseElements.  Use this parameter to explicitly specify
-        "from" objects which are not automatically locatable.
-        This could include ``Table`` objects that aren't otherwise
-        present, or ``Join`` objects whose presence will supercede
-        that of the ``Table`` objects already located in the other
-        clauses.
-
-      \**kwargs
-        Additional parameters include:
-
-        order_by
-          a scalar or list of ``ClauseElement`` objects
-          which will comprise the ``ORDER BY`` clause of the resulting
-          select.
-       
-        group_by
-          a list of ``ClauseElement`` objects which will comprise
-          the ``GROUP BY`` clause of the resulting select.
-        
-        having
-          a ``ClauseElement`` that will comprise the ``HAVING`` 
-          clause of the resulting select when ``GROUP BY`` is used.
-        
-        use_labels=False
-          when ``True``, the statement will be generated using 
-          labels for each column in the columns clause, which qualify
-          each column with its parent table's (or aliases) name so 
-          that name conflicts between columns in different tables don't
-          occur.  The format of the label is <tablename>_<column>.  The
-          "c" collection of the resulting ``Select`` object will use these
-          names as well for targeting column members.
-        
-        distinct=False
-          when ``True``, applies a ``DISTINCT`` qualifier to the 
-          columns clause of the resulting statement.
-        
-        for_update=False
-          when ``True``, applies ``FOR UPDATE`` to the end of the
-          resulting statement.  Certain database dialects also
-          support alternate values for this parameter, for example
-          mysql supports "read" which translates to ``LOCK IN SHARE MODE``,
-          and oracle supports "nowait" which translates to 
-          ``FOR UPDATE NOWAIT``.
-        
-        bind=None
-          an ``Engine`` or ``Connection`` instance to which the resulting ``Select`` 
-          object will be bound.  The ``Select`` object will otherwise
-          automatically bind to whatever ``Connectable`` instances can be located
-          within its contained ``ClauseElement`` members.
-        
-        limit=None
-          a numerical value which usually compiles to a ``LIMIT`` expression
-          in the resulting select.  Databases that don't support ``LIMIT``
-          will attempt to provide similar functionality.
-        
-        offset=None
-          a numerical value which usually compiles to an ``OFFSET`` expression
-          in the resulting select.  Databases that don't support ``OFFSET``
-          will attempt to provide similar functionality.
-        
-        scalar=False
-          deprecated.  use select(...).as_scalar() to create a "scalar column"
-          proxy for an existing Select object.
-
-        correlate=True
-          indicates that this ``Select`` object should have its contained
-          ``FromClause`` elements "correlated" to an enclosing ``Select``
-          object.  This means that any ``ClauseElement`` instance within 
-          the "froms" collection of this ``Select`` which is also present
-          in the "froms" collection of an enclosing select will not be
-          rendered in the ``FROM`` clause of this select statement.
-      
+    All arguments which accept ``ClauseElement`` arguments also accept
+    string arguments, which will be converted as appropriate into
+    either ``text()`` or ``literal_column()`` constructs.
+
+    columns
+      A list of ``ClauseElement`` objects, typically ``ColumnElement``
+      objects or subclasses, which will form the columns clause of the
+      resulting statement.  For all members which are instances of
+      ``Selectable``, the individual ``ColumnElement`` members of the
+      ``Selectable`` will be added individually to the columns clause.
+      For example, specifying a ``Table`` instance will result in all
+      the contained ``Column`` objects within to be added to the
+      columns clause.
+
+      This argument is not present on the form of ``select()``
+      available on ``Table``.
+
+    whereclause
+      A ``ClauseElement`` expression which will be used to form the
+      ``WHERE`` clause.
+
+    from_obj
+      A list of ``ClauseElement`` objects which will be added to the
+      ``FROM`` clause of the resulting statement.  Note that "from"
+      objects are automatically located within the columns and
+      whereclause ClauseElements.  Use this parameter to explicitly
+      specify "from" objects which are not automatically locatable.
+      This could include ``Table`` objects that aren't otherwise
+      present, or ``Join`` objects whose presence will supercede that
+      of the ``Table`` objects already located in the other clauses.
+
+    \**kwargs
+      Additional parameters include:
+
+      prefixes
+        a list of strings or ``ClauseElement`` objects to include
+        directly after the SELECT keyword in the generated statement,
+        for dialect-specific query features.
+
+      distinct=False
+        when ``True``, applies a ``DISTINCT`` qualifier to the columns
+        clause of the resulting statement.
+
+      use_labels=False
+        when ``True``, the statement will be generated using labels
+        for each column in the columns clause, which qualify each
+        column with its parent table's (or aliases) name so that name
+        conflicts between columns in different tables don't occur.
+        The format of the label is <tablename>_<column>.  The "c"
+        collection of the resulting ``Select`` object will use these
+        names as well for targeting column members.
+
+      for_update=False
+        when ``True``, applies ``FOR UPDATE`` to the end of the
+        resulting statement.  Certain database dialects also support
+        alternate values for this parameter, for example mysql
+        supports "read" which translates to ``LOCK IN SHARE MODE``,
+        and oracle supports "nowait" which translates to ``FOR UPDATE
+        NOWAIT``.
+
+      correlate=True
+        indicates that this ``Select`` object should have its
+        contained ``FromClause`` elements "correlated" to an enclosing
+        ``Select`` object.  This means that any ``ClauseElement``
+        instance within the "froms" collection of this ``Select``
+        which is also present in the "froms" collection of an
+        enclosing select will not be rendered in the ``FROM`` clause
+        of this select statement.
+
+      group_by
+        a list of ``ClauseElement`` objects which will comprise the
+        ``GROUP BY`` clause of the resulting select.
+
+      having
+        a ``ClauseElement`` that will comprise the ``HAVING`` clause
+        of the resulting select when ``GROUP BY`` is used.
+
+      order_by
+        a scalar or list of ``ClauseElement`` objects which will
+        comprise the ``ORDER BY`` clause of the resulting select.
+
+      limit=None
+        a numerical value which usually compiles to a ``LIMIT``
+        expression in the resulting select.  Databases that don't
+        support ``LIMIT`` will attempt to provide similar
+        functionality.
+
+      offset=None
+        a numeric value which usually compiles to an ``OFFSET``
+        expression in the resulting select.  Databases that don't
+        support ``OFFSET`` will attempt to provide similar
+        functionality.
+
+      bind=None
+        an ``Engine`` or ``Connection`` instance to which the
+        resulting ``Select ` object will be bound.  The ``Select``
+        object will otherwise automatically bind to whatever
+        ``Connectable`` instances can be located within its contained
+        ``ClauseElement`` members.
+
+      scalar=False
+        deprecated.  Use select(...).as_scalar() to create a "scalar
+        column" proxy for an existing Select object.
     """
+
     if 'scalar' in kwargs:
         util.warn_deprecated('scalar option is deprecated; see docs for details')
     scalar = kwargs.pop('scalar', False)
@@ -225,34 +236,35 @@ def select(columns=None, whereclause=None, from_obj=[], **kwargs):
 
 def subquery(alias, *args, **kwargs):
     """Return an [sqlalchemy.sql#Alias] object derived from a [sqlalchemy.sql#Select].
-    
-      name
-        alias name
 
-      \*args, \**kwargs
-        all other arguments are delivered to the [sqlalchemy.sql#select()] function.
-    
+    name
+      alias name
+
+    \*args, \**kwargs
+
+      all other arguments are delivered to the [sqlalchemy.sql#select()]
+      function.
     """
-    
+
     return Select(*args, **kwargs).alias(alias)
 
 def insert(table, values = None, **kwargs):
     """Return an [sqlalchemy.sql#Insert] clause element.
 
-    Similar functionality is available via the ``insert()`` 
-    method on [sqlalchemy.schema#Table].
+    Similar functionality is available via the ``insert()`` method on
+    [sqlalchemy.schema#Table].
 
-      table
-        The table to be inserted into.
+    table
+      The table to be inserted into.
 
-      values
-        A dictionary which specifies the column specifications of the
-        ``INSERT``, and is optional.  If left as None, the column
-        specifications are determined from the bind parameters used
-        during the compile phase of the ``INSERT`` statement.  If the
-        bind parameters also are None during the compile phase, then the
-        column specifications will be generated from the full list of
-        table columns.
+    values
+      A dictionary which specifies the column specifications of the
+      ``INSERT``, and is optional.  If left as None, the column
+      specifications are determined from the bind parameters used
+      during the compile phase of the ``INSERT`` statement.  If the
+      bind parameters also are None during the compile phase, then the
+      column specifications will be generated from the full list of
+      table columns.
 
     If both `values` and compile-time bind parameters are present, the
     compile-time bind parameters override the information specified
@@ -275,24 +287,24 @@ def insert(table, values = None, **kwargs):
 def update(table, whereclause = None, values = None, **kwargs):
     """Return an [sqlalchemy.sql#Update] clause element.
 
-    Similar functionality is available via the ``update()`` 
-    method on [sqlalchemy.schema#Table].
+    Similar functionality is available via the ``update()`` method on
+    [sqlalchemy.schema#Table].
 
-      table
-        The table to be updated.
+    table
+      The table to be updated.
 
-      whereclause
-        A ``ClauseElement`` describing the ``WHERE`` condition of the
-        ``UPDATE`` statement.
+    whereclause
+      A ``ClauseElement`` describing the ``WHERE`` condition of the
+      ``UPDATE`` statement.
 
-      values
-        A dictionary which specifies the ``SET`` conditions of the
-        ``UPDATE``, and is optional. If left as None, the ``SET``
-        conditions are determined from the bind parameters used during
-        the compile phase of the ``UPDATE`` statement.  If the bind
-        parameters also are None during the compile phase, then the
-        ``SET`` conditions will be generated from the full list of table
-        columns.
+    values
+      A dictionary which specifies the ``SET`` conditions of the
+      ``UPDATE``, and is optional. If left as None, the ``SET``
+      conditions are determined from the bind parameters used during
+      the compile phase of the ``UPDATE`` statement.  If the bind
+      parameters also are None during the compile phase, then the
+      ``SET`` conditions will be generated from the full list of table
+      columns.
 
     If both `values` and compile-time bind parameters are present, the
     compile-time bind parameters override the information specified
@@ -315,16 +327,15 @@ def update(table, whereclause = None, values = None, **kwargs):
 def delete(table, whereclause = None, **kwargs):
     """Return a [sqlalchemy.sql#Delete] clause element.
 
-    Similar functionality is available via the ``delete()`` 
-    method on [sqlalchemy.schema#Table].
-
-      table
-        The table to be updated.
+    Similar functionality is available via the ``delete()`` method on
+    [sqlalchemy.schema#Table].
 
-      whereclause
-        A ``ClauseElement`` describing the ``WHERE`` condition of the
-        ``UPDATE`` statement.
+    table
+      The table to be updated.
 
+    whereclause
+      A ``ClauseElement`` describing the ``WHERE`` condition of the
+      ``UPDATE`` statement.
     """
 
     return Delete(table, whereclause, **kwargs)
@@ -332,8 +343,9 @@ def delete(table, whereclause = None, **kwargs):
 def and_(*clauses):
     """Join a list of clauses together using the ``AND`` operator.
 
-    The ``&`` operator is also overloaded on all [sqlalchemy.sql#_CompareMixin]
-    subclasses to produce the same result.
+    The ``&`` operator is also overloaded on all
+    [sqlalchemy.sql#_CompareMixin] subclasses to produce the same
+    result.
     """
     if len(clauses) == 1:
         return clauses[0]
@@ -342,8 +354,9 @@ def and_(*clauses):
 def or_(*clauses):
     """Join a list of clauses together using the ``OR`` operator.
 
-    The ``|`` operator is also overloaded on all [sqlalchemy.sql#_CompareMixin]
-    subclasses to produce the same result.
+    The ``|`` operator is also overloaded on all
+    [sqlalchemy.sql#_CompareMixin] subclasses to produce the same
+    result.
     """
 
     if len(clauses) == 1:
@@ -353,15 +366,16 @@ def or_(*clauses):
 def not_(clause):
     """Return a negation of the given clause, i.e. ``NOT(clause)``.
 
-    The ``~`` operator is also overloaded on all [sqlalchemy.sql#_CompareMixin]
-    subclasses to produce the same result.
+    The ``~`` operator is also overloaded on all
+    [sqlalchemy.sql#_CompareMixin] subclasses to produce the same
+    result.
     """
 
     return operators.inv(clause)
 
 def distinct(expr):
-    """return a ``DISTINCT`` clause."""
-    
+    """Return a ``DISTINCT`` clause."""
+
     return _UnaryExpression(expr, operator=operators.distinct_op)
 
 def between(ctest, cleft, cright):
@@ -380,18 +394,18 @@ def between(ctest, cleft, cright):
 def case(whens, value=None, else_=None):
     """Produce a ``CASE`` statement.
 
-        whens
-          A sequence of pairs to be translated into "when / then" clauses.
-
-        value
-          Optional for simple case statements.
+    whens
+      A sequence of pairs to be translated into "when / then" clauses.
 
-        else\_
-          Optional as well, for case defaults.
+    value
+      Optional for simple case statements.
 
+    else\_
+      Optional as well, for case defaults.
     """
 
-    whenlist = [ClauseList('WHEN', c, 'THEN', r, operator=None) for (c,r) in whens]
+    whenlist = [ClauseList('WHEN', c, 'THEN', r, operator=None)
+                for (c,r) in whens]
     if not else_ is None:
         whenlist.append(ClauseList('ELSE', else_, operator=None))
     if whenlist:
@@ -425,128 +439,128 @@ def extract(field, expr):
 
 def exists(*args, **kwargs):
     """Return an ``EXISTS`` clause as applied to a [sqlalchemy.sql#Select] object.
-    
-    The resulting [sqlalchemy.sql#_Exists] object can be executed by itself
-    or used as a subquery within an enclosing select.
-    
-        \*args, \**kwargs
-          all arguments are sent directly to the [sqlalchemy.sql#select()] function
-          to produce a ``SELECT`` statement.
-          
+
+    The resulting [sqlalchemy.sql#_Exists] object can be executed by
+    itself or used as a subquery within an enclosing select.
+
+    \*args, \**kwargs
+      all arguments are sent directly to the [sqlalchemy.sql#select()]
+      function to produce a ``SELECT`` statement.
     """
-    
+
     return _Exists(*args, **kwargs)
 
 def union(*selects, **kwargs):
     """Return a ``UNION`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
-    
-    A similar ``union()`` method is available on all [sqlalchemy.sql#FromClause]
-    subclasses.
-    
-      \*selects
-        a list of [sqlalchemy.sql#Select] instances.
-
-      \**kwargs
-         available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-    
+
+    A similar ``union()`` method is available on all
+    [sqlalchemy.sql#FromClause] subclasses.
+
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+       available keyword arguments are the same as those of
+       [sqlalchemy.sql#select()].
     """
-    
+
     return _compound_select('UNION', *selects, **kwargs)
 
 def union_all(*selects, **kwargs):
     """Return a ``UNION ALL`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
-    
-    A similar ``union_all()`` method is available on all [sqlalchemy.sql#FromClause]
-    subclasses.
 
-        \*selects
-          a list of [sqlalchemy.sql#Select] instances.
-        
-        \**kwargs
-          available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-          
+    A similar ``union_all()`` method is available on all
+    [sqlalchemy.sql#FromClause] subclasses.
+
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+      available keyword arguments are the same as those of
+      [sqlalchemy.sql#select()].
     """
+
     return _compound_select('UNION ALL', *selects, **kwargs)
 
 def except_(*selects, **kwargs):
     """Return an ``EXCEPT`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
 
-        \*selects
-          a list of [sqlalchemy.sql#Select] instances.
-        
-        \**kwargs
-          available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-          
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+      available keyword arguments are the same as those of
+      [sqlalchemy.sql#select()].
     """
     return _compound_select('EXCEPT', *selects, **kwargs)
 
 def except_all(*selects, **kwargs):
     """Return an ``EXCEPT ALL`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
 
-        \*selects
-          a list of [sqlalchemy.sql#Select] instances.
-        
-        \**kwargs
-          available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-          
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+      available keyword arguments are the same as those of
+      [sqlalchemy.sql#select()].
     """
     return _compound_select('EXCEPT ALL', *selects, **kwargs)
 
 def intersect(*selects, **kwargs):
     """Return an ``INTERSECT`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
 
-        \*selects
-          a list of [sqlalchemy.sql#Select] instances.
-        
-        \**kwargs
-          available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-          
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+      available keyword arguments are the same as those of
+      [sqlalchemy.sql#select()].
     """
     return _compound_select('INTERSECT', *selects, **kwargs)
 
 def intersect_all(*selects, **kwargs):
     """Return an ``INTERSECT ALL`` of multiple selectables.
-    
+
     The returned object is an instance of [sqlalchemy.sql#CompoundSelect].
 
-        \*selects
-          a list of [sqlalchemy.sql#Select] instances.
-        
-        \**kwargs
-          available keyword arguments are the same as those of [sqlalchemy.sql#select()].
-          
+    \*selects
+      a list of [sqlalchemy.sql#Select] instances.
+
+    \**kwargs
+      available keyword arguments are the same as those of
+      [sqlalchemy.sql#select()].
     """
     return _compound_select('INTERSECT ALL', *selects, **kwargs)
 
 def alias(selectable, alias=None):
     """Return an [sqlalchemy.sql#Alias] object.
-    
+
     An ``Alias`` represents any [sqlalchemy.sql#FromClause] with
     an alternate name assigned within SQL, typically using the ``AS``
     clause when generated, e.g. ``SELECT * FROM table AS aliasname``.
-    
-    Similar functionality is available via the ``alias()`` method 
+
+    Similar functionality is available via the ``alias()`` method
     available on all ``FromClause`` subclasses.
-    
+
       selectable
-        any ``FromClause`` subclass, such as a table, select statement, etc..
-        
+        any ``FromClause`` subclass, such as a table, select
+        statement, etc..
+
       alias
-        string name to be assigned as the alias.  If ``None``, a random
-        name will be generated.
-        
+        string name to be assigned as the alias.  If ``None``, a
+        random name will be generated.
     """
-        
+
     return Alias(selectable, alias=alias)
 
 
@@ -554,87 +568,80 @@ def literal(value, type_=None):
     """Return a literal clause, bound to a bind parameter.
 
     Literal clauses are created automatically when non-
-    ``ClauseElement`` objects (such as strings, ints, dates, etc.) are used in 
-    a comparison operation with a [sqlalchemy.sql#_CompareMixin]
-    subclass, such as a ``Column`` object.  Use this function
-    to force the generation of a literal clause, which will 
-    be created as a [sqlalchemy.sql#_BindParamClause] with a bound
-    value.
-    
-      value
-        the value to be bound.  can be any Python object supported by
-        the underlying DBAPI, or is translatable via the given type
-        argument.
-    
-      type\_
-        an optional [sqlalchemy.types#TypeEngine] which will provide
-        bind-parameter translation for this literal.
-
+    ``ClauseElement`` objects (such as strings, ints, dates, etc.) are
+    used in a comparison operation with a
+    [sqlalchemy.sql#_CompareMixin] subclass, such as a ``Column``
+    object.  Use this function to force the generation of a literal
+    clause, which will be created as a
+    [sqlalchemy.sql#_BindParamClause] with a bound value.
+
+    value
+      the value to be bound.  Can be any Python object supported by
+      the underlying DBAPI, or is translatable via the given type
+      argument.
+
+    type\_
+      an optional [sqlalchemy.types#TypeEngine] which will provide
+      bind-parameter translation for this literal.
     """
 
     return _BindParamClause('literal', value, type_=type_, unique=True)
 
 def label(name, obj):
     """Return a [sqlalchemy.sql#_Label] object for the given [sqlalchemy.sql#ColumnElement].
-    
-    A label changes the name of an element in the columns clause 
-    of a ``SELECT`` statement, typically via the ``AS`` SQL keyword.
-    
-    This functionality is more conveniently available via 
-    the ``label()`` method on ``ColumnElement``.
-    
-      name
-        label name
-        
-      obj
-        a ``ColumnElement``.
-        
+
+    A label changes the name of an element in the columns clause of a
+    ``SELECT`` statement, typically via the ``AS`` SQL keyword.
+
+    This functionality is more conveniently available via the
+    ``label()`` method on ``ColumnElement``.
+
+    name
+      label name
+
+    obj
+      a ``ColumnElement``.
     """
 
     return _Label(name, obj)
 
 def column(text, type_=None):
-    """Return a textual column clause, as would be in the columns 
-    clause of a ``SELECT`` statement.
-    
+    """Return a textual column clause, as would be in the columns clause of a ``SELECT`` statement.
+
     The object returned is an instance of [sqlalchemy.sql#_ColumnClause],
     which represents the "syntactical" portion of the schema-level
     [sqlalchemy.schema#Column] object.
-    
-      text
-        the name of the column.  Quoting rules will be applied to 
-        the clause like any other column name.  For textual column
-        constructs that are not to be quoted, use the [sqlalchemy.sql#literal_column()]
-        function.
-        
-      type\_
-        an optional [sqlalchemy.types#TypeEngine] object which will provide
-        result-set translation for this column.
-        
+
+    text
+      the name of the column.  Quoting rules will be applied to the
+      clause like any other column name.  For textual column
+      constructs that are not to be quoted, use the
+      [sqlalchemy.sql#literal_column()] function.
+
+    type\_
+      an optional [sqlalchemy.types#TypeEngine] object which will
+      provide result-set translation for this column.
+
     """
 
     return _ColumnClause(text, type_=type_)
 
 def literal_column(text, type_=None):
-    """Return a textual column clause, as would be in the columns
-    clause of a ``SELECT`` statement.
-  
+    """Return a textual column clause, as would be in the columns clause of a ``SELECT`` statement.
+
     The object returned is an instance of [sqlalchemy.sql#_ColumnClause],
     which represents the "syntactical" portion of the schema-level
     [sqlalchemy.schema#Column] object.
-    
-  
-      text
-        the name of the column.  Quoting rules will not be applied 
-        to the column.   For textual column
-        constructs that should be quoted like any other column 
-        construct, use the [sqlalchemy.sql#column()]
-        function.
-      
-      type
-        an optional [sqlalchemy.types#TypeEngine] object which will provide
-        result-set translation for this column.
-      
+
+    text
+      the name of the column.  Quoting rules will not be applied to
+      the column.  For textual column constructs that should be quoted
+      like any other column construct, use the
+      [sqlalchemy.sql#column()] function.
+
+    type
+      an optional [sqlalchemy.types#TypeEngine] object which will
+      provide result-set translation for this column.
     """
 
     return _ColumnClause(text, type_=type_, is_literal=True)
@@ -642,8 +649,8 @@ def literal_column(text, type_=None):
 def table(name, *columns):
     """Return a [sqlalchemy.sql#Table] object.
 
-    This is a primitive version of the [sqlalchemy.schema#Table] object, which
-    is a subclass of this object.
+    This is a primitive version of the [sqlalchemy.schema#Table] object,
+    which is a subclass of this object.
     """
 
     return TableClause(name, *columns)
@@ -651,22 +658,23 @@ def table(name, *columns):
 def bindparam(key, value=None, type_=None, shortname=None, unique=False):
     """Create a bind parameter clause with the given key.
 
-        value
-         a default value for this bind parameter.  a bindparam with a value
-         is called a ``value-based bindparam``.
+    value
+      a default value for this bind parameter.  a bindparam with a
+      value is called a ``value-based bindparam``.
 
-        shortname
-         an ``alias`` for this bind parameter.  usually used to alias the ``key`` and 
-         ``label`` of a column, i.e. ``somecolname`` and ``sometable_somecolname``
+    shortname
+      an ``alias`` for this bind parameter.  usually used to alias the
+      ``key`` nd ``label`` of a column, i.e. ``somecolname`` and
+      ``sometable_somecolname``
 
-        type
-         a sqlalchemy.types.TypeEngine object indicating the type of this bind param, will
-         invoke type-specific bind parameter processing
+    type
+      a sqlalchemy.types.TypeEngine object indicating the type of this
+      bind param, will invoke type-specific bind parameter processing
 
-        unique
-         if True, bind params sharing the same name will have their underlying ``key`` modified
-         to a uniquely generated name.  mostly useful with value-based bind params.
-       
+    unique
+      if True, bind params sharing the same name will have their
+      underlying ``key`` modified to a uniquely generated name.
+      mostly useful with value-based bind params.
     """
 
     if isinstance(key, _ColumnClause):
@@ -675,16 +683,16 @@ def bindparam(key, value=None, type_=None, shortname=None, unique=False):
         return _BindParamClause(key, value, type_=type_, shortname=shortname, unique=unique)
 
 def outparam(key, type_=None):
-    """create an 'OUT' parameter for usage in functions (stored procedures), for databases 
-    whith support them.
-    
-    The ``outparam`` can be used like a regular function parameter.  The "output" value will
-    be available from the [sqlalchemy.engine#ResultProxy] object via its ``out_parameters``
+    """Create an 'OUT' parameter for usage in functions (stored procedures), for databases which support them.
+
+    The ``outparam`` can be used like a regular function parameter.
+    The "output" value will be available from the
+    [sqlalchemy.engine#ResultProxy] object via its ``out_parameters``
     attribute, which returns a dictionary containing the values.
     """
-    
+
     return _BindParamClause(key, None, type_=type_, unique=False, isoutparam=True)
-    
+
 def text(text, bind=None, *args, **kwargs):
     """Create literal text to be inserted into a query.
 
@@ -695,28 +703,27 @@ def text(text, bind=None, *args, **kwargs):
     outside of other ``ClauseElement`` objects, or optionally wherever
     plain text is to be used.
 
-      text
-        The text of the SQL statement to be created.  use ``:<param>``
-        to specify bind parameters; they will be compiled to their
-        engine-specific format.
-
-      bind
-        An optional connection or engine to be used for this text query.
-        
-      bindparams
-        A list of ``bindparam()`` instances which can be used to define
-        the types and/or initial values for the bind parameters within
-        the textual statement; the keynames of the bindparams must match
-        those within the text of the statement.  The types will be used
-        for pre-processing on bind values.
-
-      typemap
-        A dictionary mapping the names of columns represented in the
-        ``SELECT`` clause of the textual statement to type objects,
-        which will be used to perform post-processing on columns within
-        the result set (for textual statements that produce result
-        sets).
-
+    text
+      the text of the SQL statement to be created.  use ``:<param>``
+      to specify bind parameters; they will be compiled to their
+      engine-specific format.
+
+    bind
+      an optional connection or engine to be used for this text query.
+
+    bindparams
+      a list of ``bindparam()`` instances which can be used to define
+      the types and/or initial values for the bind parameters within
+      the textual statement; the keynames of the bindparams must match
+      those within the text of the statement.  The types will be used
+      for pre-processing on bind values.
+
+    typemap
+      a dictionary mapping the names of columns represented in the
+      ``SELECT`` clause of the textual statement to type objects,
+      which will be used to perform post-processing on columns within
+      the result set (for textual statements that produce result
+      sets).
     """
 
     return _TextClause(text, bind=bind, *args, **kwargs)
@@ -740,7 +747,7 @@ class _FunctionGenerator(object):
                 return self.__dict__[name]
             except KeyError:
                 raise AttributeError(name)
-                
+
         elif name.startswith('_'):
             name = name[0:-1]
         f = _FunctionGenerator(**self.opts)
@@ -757,7 +764,7 @@ func = _FunctionGenerator()
 # TODO: use UnaryExpression for this instead ?
 modifier = _FunctionGenerator(group=False)
 
-    
+
 def _compound_select(keyword, *selects, **kwargs):
     return CompoundSelect(keyword, *selects, **kwargs)
 
@@ -779,7 +786,7 @@ def _literal_as_column(element):
         return literal_column(str(element))
     else:
         return element
-    
+
 def _literal_as_binds(element, name='literal', type_=None):
     if isinstance(element, Operators):
         return element.expression_element()
@@ -798,17 +805,19 @@ def _selectable(element):
         return element
     else:
         raise exceptions.ArgumentError("Object '%s' is not a Selectable and does not implement `__selectable__()`" % repr(element))
-        
+
 def is_column(col):
+    """True if ``col`` is an instance of ``ColumnElement``."""
     return isinstance(col, ColumnElement)
 
 class ClauseParameters(object):
     """Represent a dictionary/iterator of bind parameter key names/values.
 
-    Tracks the original [sqlalchemy.sql#_BindParamClause] objects as well as the
-    keys/position of each parameter, and can return parameters as a
-    dictionary or a list.  Will process parameter values according to
-    the ``TypeEngine`` objects present in the ``_BindParamClause`` instances.
+    Tracks the original [sqlalchemy.sql#_BindParamClause] objects
+    as well as the keys/position of each parameter, and can return
+    parameters as a dictionary or a list.  Will process parameter
+    values according to the ``TypeEngine`` objects present in the
+    ``_BindParamClause`` instances.
     """
 
     def __init__(self, dialect, positional=None):
@@ -821,7 +830,7 @@ class ClauseParameters(object):
 
     def set_parameter(self, bindparam, value, name):
         self.__binds[name] = [bindparam, name, value]
-        
+
     def get_original(self, key):
         return self.__binds[key][2]
 
@@ -831,34 +840,34 @@ class ClauseParameters(object):
     def get_processors(self):
         """return a dictionary of bind 'processing' functions"""
         return dict([
-            (key, value) for key, value in 
+            (key, value) for key, value in
             [(
                 key,
                 self.__binds[key][0].bind_processor(self.dialect)
             ) for key in self.__binds]
             if value is not None
         ])
-    
+
     def get_processed(self, key, processors):
         return key in processors and processors[key](self.__binds[key][2]) or self.__binds[key][2]
-            
+
     def keys(self):
         return self.__binds.keys()
 
     def __iter__(self):
         return iter(self.keys())
-        
+
     def __getitem__(self, key):
         (bind, name, value) = self.__binds[key]
         processor = bind.bind_processor(self.dialect)
         return processor is not None and processor(value) or value
+
     def __contains__(self, key):
         return key in self.__binds
-    
+
     def set_value(self, key, value):
         self.__binds[key][2] = value
-            
+
     def get_original_dict(self):
         return dict([(name, value) for (b, name, value) in self.__binds.values()])
 
@@ -867,7 +876,7 @@ class ClauseParameters(object):
             return processors[key](self.__binds[key][2])
         else:
             return self.__binds[key][2]
-            
+
     def get_raw_list(self, processors):
         return [self.__get_processed(key, processors) for key in self.positional]
 
@@ -893,32 +902,29 @@ class ClauseParameters(object):
         return self.__class__.__name__ + ":" + repr(self.get_original_dict())
 
 class ClauseVisitor(object):
-    """A class that knows how to traverse and visit
-    ``ClauseElements``.
-    
-    Calls visit_XXX() methods dynamically generated for each particualr
-    ``ClauseElement`` subclass encountered.  Traversal of a
-    hierarchy of ``ClauseElements`` is achieved via the
-    ``traverse()`` method, which is passed the lead
-    ``ClauseElement``.
-    
-    By default, ``ClauseVisitor`` traverses all elements
-    fully.  Options can be specified at the class level via the 
-    ``__traverse_options__`` dictionary which will be passed
-    to the ``get_children()`` method of each ``ClauseElement``;
-    these options can indicate modifications to the set of 
-    elements returned, such as to not return column collections
-    (column_collections=False) or to return Schema-level items
-    (schema_visitor=True).
-    
+    """A class that knows how to traverse and visit ``ClauseElements``.
+
+    Calls visit_XXX() methods dynamically generated for each
+    particualr ``ClauseElement`` subclass encountered.  Traversal of a
+    hierarchy of ``ClauseElements`` is achieved via the ``traverse()``
+    method, which is passed the lead ``ClauseElement``.
+
+    By default, ``ClauseVisitor`` traverses all elements fully.
+    Options can be specified at the class level via the
+    ``__traverse_options__`` dictionary which will be passed to the
+    ``get_children()`` method of each ``ClauseElement``; these options
+    can indicate modifications to the set of elements returned, such
+    as to not return column collections (column_collections=False) or
+    to return Schema-level items (schema_visitor=True).
+
     ``ClauseVisitor`` also supports a simultaneous copy-and-traverse
     operation, which will produce a copy of a given ``ClauseElement``
-    structure while at the same time allowing ``ClauseVisitor`` subclasses
-    to modify the new structure in-place.
-    
+    structure while at the same time allowing ``ClauseVisitor``
+    subclasses to modify the new structure in-place.
     """
+
     __traverse_options__ = {}
-    
+
     def traverse_single(self, obj, **kwargs):
         meth = getattr(self, "visit_%s" % obj.__visit_name__, None)
         if meth:
@@ -934,11 +940,11 @@ class ClauseVisitor(object):
                 traversal.insert(0, t)
                 for c in t.get_children(**self.__traverse_options__):
                     stack.append(c)
-        
+
     def traverse(self, obj, stop_on=None, clone=False):
         if clone:
             obj = obj._clone()
-            
+
         stack = [obj]
         traversal = []
         while len(stack) > 0:
@@ -960,8 +966,10 @@ class ClauseVisitor(object):
 
     def chain(self, visitor):
         """'chain' an additional ClauseVisitor onto this ClauseVisitor.
-        
-        the chained visitor will receive all visit events after this one."""
+
+        The chained visitor will receive all visit events after this one.
+        """
+
         tail = self
         while getattr(tail, '_next', None) is not None:
             tail = tail._next
@@ -969,16 +977,19 @@ class ClauseVisitor(object):
         return self
 
 class NoColumnVisitor(ClauseVisitor):
-    """a ClauseVisitor that will not traverse the exported Column 
-    collections on Table, Alias, Select, and CompoundSelect objects
-    (i.e. their 'columns' or 'c' attribute).
-    
-    this is useful because most traversals don't need those columns, or
-    in the case of ANSICompiler it traverses them explicitly; so
-    skipping their traversal here greatly cuts down on method call overhead.
+    """A ClauseVisitor that will not traverse exported column collections.
+
+    Will not traverse the exported Column collections on Table, Alias,
+    Select, and CompoundSelect objects (i.e. their 'columns' or 'c'
+    attribute).
+
+    This is useful because most traversals don't need those columns,
+    or in the case of ANSICompiler it traverses them explicitly; so
+    skipping their traversal here greatly cuts down on method call
+    overhead.
     """
-    
-    __traverse_options__ = {'column_collections':False}
+
+    __traverse_options__ = {'column_collections': False}
 
 
 class _FigureVisitName(type):
@@ -989,20 +1000,19 @@ class _FigureVisitName(type):
             x = re.sub(r'(?!^)[A-Z]', lambda m:'_'+m.group(0).lower(), x)
             cls.__visit_name__ = x.lower()
         super(_FigureVisitName, cls).__init__(clsname, bases, dict)
-        
+
 class ClauseElement(object):
-    """Base class for elements of a programmatically constructed SQL
-    expression.
-    """
+    """Base class for elements of a programmatically constructed SQL expression."""
     __metaclass__ = _FigureVisitName
-    
+
     def _clone(self):
-        """create a shallow copy of this ClauseElement.
-        
-        This method may be used by a generative API.
-        Its also used as part of the "deep" copy afforded
-        by a traversal that combines the _copy_internals()
-        method."""
+        """Create a shallow copy of this ClauseElement.
+
+        This method may be used by a generative API.  Its also used as
+        part of the "deep" copy afforded by a traversal that combines
+        the _copy_internals() method.
+        """
+
         c = self.__class__.__new__(self.__class__)
         c.__dict__ = self.__dict__.copy()
         return c
@@ -1017,41 +1027,40 @@ class ClauseElement(object):
         raise NotImplementedError(repr(self))
 
     def _hide_froms(self, **modifiers):
-        """Return a list of ``FROM`` clause elements which this
-        ``ClauseElement`` replaces.
-        """
+        """Return a list of ``FROM`` clause elements which this ``ClauseElement`` replaces."""
 
         return []
 
     def unique_params(self, *optionaldict, **kwargs):
-        """same functionality as ``params()``, except adds `unique=True` to affected
-        bind parameters so that multiple statements can be used.
+        """Return a copy with ``bindparam()`` elments replaced.
+
+        Same functionality as ``params()``, except adds `unique=True`
+        to affected bind parameters so that multiple statements can be
+        used.
         """
-        
+
         return self._params(True, optionaldict, kwargs)
     def params(self, *optionaldict, **kwargs):
-        """return a copy of this ClauseElement, with ``bindparam()`` elements
-        replaced with values taken from the given dictionary.
-        
-            e.g.::
-            
-                >>> clause = column('x') + bindparam('foo')
-                >>> print clause.compile().params
-                {'foo':None}
-                
-                >>> print clause.params({'foo':7}).compile().params
-                {'foo':7}
-        
+        """Return a copy with ``bindparam()`` elments replaced.
+
+        Returns a copy of this ClauseElement with ``bindparam()``
+        elements replaced with values taken from the given dictionary::
+
+          >>> clause = column('x') + bindparam('foo')
+          >>> print clause.compile().params
+          {'foo':None}
+          >>> print clause.params({'foo':7}).compile().params
+          {'foo':7}
         """
-        
+
         return self._params(False, optionaldict, kwargs)
-    
+
     def _params(self, unique, optionaldict, kwargs):
         if len(optionaldict) == 1:
             kwargs.update(optionaldict[0])
         elif len(optionaldict) > 1:
             raise exceptions.ArgumentError("params() takes zero or one positional dictionary argument")
-            
+
         class Vis(ClauseVisitor):
             def visit_bindparam(self, bind):
                 if bind.key in kwargs:
@@ -1059,7 +1068,7 @@ class ClauseElement(object):
                 if unique:
                     bind.unique=True
         return Vis().traverse(self, clone=True)
-        
+
     def compare(self, other):
         """Compare this ClauseElement to the given ClauseElement.
 
@@ -1070,32 +1079,32 @@ class ClauseElement(object):
         return self is other
 
     def _copy_internals(self):
-        """reassign internal elements to be clones of themselves.
-        
-        called during a copy-and-traverse operation on newly 
-        shallow-copied elements to create a deep copy."""
-        
+        """Reassign internal elements to be clones of themselves.
+
+        Called during a copy-and-traverse operation on newly
+        shallow-copied elements to create a deep copy.
+        """
+
         pass
-        
+
     def get_children(self, **kwargs):
-        """return immediate child elements of this ``ClauseElement``.
-        
-        this is used for visit traversal.
-        
-        \**kwargs may contain flags that change the collection
-        that is returned, for example to return a subset of items
-        in order to cut down on larger traversals, or to return 
-        child items from a different context (such as schema-level
-        collections instead of clause-level)."""
+        """Return immediate child elements of this ``ClauseElement``.
+
+        This is used for visit traversal.
+
+        \**kwargs may contain flags that change the collection that is
+        returned, for example to return a subset of items in order to
+        cut down on larger traversals, or to return child items from a
+        different context (such as schema-level collections instead of
+        clause-level).
+        """
         return []
-    
+
     def self_group(self, against=None):
         return self
 
     def supports_execution(self):
-        """Return True if this clause element represents a complete
-        executable statement.
-        """
+        """Return True if this clause element represents a complete executable statement."""
 
         return False
 
@@ -1120,7 +1129,7 @@ class ClauseElement(object):
                 return engine
         else:
             return None
-    
+
     bind = property(lambda s:s._find_engine(), doc="""Returns the Engine or Connection to which this ClauseElement is bound, or None if none found.""")
 
     def execute(self, *multiparams, **params):
@@ -1133,9 +1142,7 @@ class ClauseElement(object):
         return self.compile(bind=self.bind, parameters=compile_params).execute(*multiparams, **params)
 
     def scalar(self, *multiparams, **params):
-        """Compile and execute this ``ClauseElement``, returning the
-        result's scalar representation.
-        """
+        """Compile and execute this ``ClauseElement``, returning the result's scalar representation."""
 
         return self.execute(*multiparams, **params).scalar()
 
@@ -1144,8 +1151,9 @@ class ClauseElement(object):
 
         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.
+        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
         ``ANSIDialect`` to create a default ``Compiler``.
@@ -1218,7 +1226,8 @@ class Operators(object):
         raise NotImplementedError()
 
 class ColumnOperators(Operators):
-    """defines comparison and math operations"""
+    """Defines comparison and math operations."""
+
     def __lt__(self, other):
         return self.operate(operators.lt, other)
 
@@ -1239,25 +1248,25 @@ class ColumnOperators(Operators):
 
     def concat(self, other):
         return self.operate(operators.concat_op, other)
-        
+
     def like(self, other):
         return self.operate(operators.like_op, other)
-    
+
     def in_(self, *other):
         return self.operate(operators.in_op, other)
-    
+
     def startswith(self, other):
         return self.operate(operators.startswith_op, other)
 
     def endswith(self, other):
         return self.operate(operators.endswith_op, other)
-    
+
     def desc(self):
         return self.operate(operators.desc_op)
-        
+
     def asc(self):
         return self.operate(operators.asc_op)
-        
+
     def __radd__(self, other):
         return self.reverse_operate(operators.add, other)
 
@@ -1275,7 +1284,7 @@ class ColumnOperators(Operators):
 
     def distinct(self):
         return self.operate(operators.distinct_op)
-        
+
     def __add__(self, other):
         return self.operate(operators.add, other)
 
@@ -1294,8 +1303,9 @@ class ColumnOperators(Operators):
     def __truediv__(self, other):
         return self.operate(operators.truediv, other)
 
-# precedence ordering for common operators.  if an operator is not present in this list,
-# it will be parenthesized when grouped against other operators
+# precedence ordering for common operators.  if an operator is not
+# present in this list, it will be parenthesized when grouped against
+# other operators
 _smallest = object()
 _largest = object()
 
@@ -1346,21 +1356,18 @@ class _CompareMixin(ColumnOperators):
                 raise exceptions.ArgumentError("Only '='/'!=' operators can be used with NULL")
         else:
             obj = self._check_literal(obj)
-
-            
         return _BinaryExpression(self.expression_element(), obj, op, type_=sqltypes.Boolean, negate=negate)
 
     def __operate(self, op, obj):
         obj = self._check_literal(obj)
 
         type_ = self._compare_type(obj)
-        
-        # TODO: generalize operator overloading like this out into the types module
+
+        # TODO: generalize operator overloading like this out into the
+        # types module
         if op == operators.add and isinstance(type_, (sqltypes.Concatenable)):
             op = operators.concat_op
-        
         return _BinaryExpression(self.expression_element(), obj, op, type_=type_)
-
     operators = {
         operators.add : (__operate,),
         operators.mul : (__operate,),
@@ -1380,13 +1387,13 @@ class _CompareMixin(ColumnOperators):
     def operate(self, op, *other):
         o = _CompareMixin.operators[op]
         return o[0](self, op, other[0], *o[1:])
-    
+
     def reverse_operate(self, op, other):
         return self._bind_param(other).operate(op, self)
 
     def in_(self, *other):
         return self._in_impl(operators.in_op, operators.notin_op, *other)
-        
+
     def _in_impl(self, op, negate_op, *other):
         if len(other) == 0:
             return _Grouping(case([(self.__eq__(None), text('NULL'))], else_=text('0')).__eq__(text('1')))
@@ -1409,14 +1416,14 @@ class _CompareMixin(ColumnOperators):
         return self.__compare(op, ClauseList(*args).self_group(against=op), negate=negate_op)
 
     def startswith(self, other):
-        """produce the clause ``LIKE '<other>%'``"""
+        """Produce the clause ``LIKE '<other>%'``"""
 
         perc = isinstance(other,(str,unicode)) and '%' or literal('%',type_= sqltypes.String)
         return self.__compare(operators.like_op, other + perc)
 
     def endswith(self, other):
-        """produce the clause ``LIKE '%<other>'``"""
-        
+        """Produce the clause ``LIKE '%<other>'``"""
+
         if isinstance(other,(str,unicode)): po = '%' + other
         else:
             po = literal('%', type_=sqltypes.String) + other
@@ -1424,44 +1431,43 @@ class _CompareMixin(ColumnOperators):
         return self.__compare(operators.like_op, po)
 
     def label(self, name):
-        """produce a column label, i.e. ``<columnname> AS <name>``"""
+        """Produce a column label, i.e. ``<columnname> AS <name>``"""
         return _Label(name, self, self.type)
-    
+
     def desc(self):
-        """produce a DESC clause, i.e. ``<columnname> DESC``"""
-        
+        """Produce a DESC clause, i.e. ``<columnname> DESC``"""
+
         return desc(self)
-        
+
     def asc(self):
-        """produce a ASC clause, i.e. ``<columnname> ASC``"""
-        
+        """Produce a ASC clause, i.e. ``<columnname> ASC``"""
+
         return asc(self)
-        
+
     def distinct(self):
-        """produce a DISTINCT clause, i.e. ``DISTINCT <columnname>``"""
+        """Produce a DISTINCT clause, i.e. ``DISTINCT <columnname>``"""
         return _UnaryExpression(self, operator=operators.distinct_op)
 
     def between(self, cleft, cright):
-        """produce a BETWEEN clause, i.e. ``<column> BETWEEN <cleft> AND <cright>``"""
+        """Produce a BETWEEN clause, i.e. ``<column> BETWEEN <cleft> AND <cright>``"""
 
         return _BinaryExpression(self, ClauseList(self._check_literal(cleft), self._check_literal(cright), operator=operators.and_, group=False), operators.between_op)
 
     def op(self, operator):
         """produce a generic operator function.
-        
-        e.g.
-        
-            somecolumn.op("*")(5)
-            
-        produces
-        
-            somecolumn * 5
-            
+
+        e.g.::
+
+          somecolumn.op("*")(5)
+
+        produces::
+
+          somecolumn * 5
+
         operator
-            a string which will be output as the infix operator 
-            between this ``ClauseElement`` and the expression 
-            passed to the generated function.
-            
+          a string which will be output as the infix operator between
+          this ``ClauseElement`` and the expression passed to the
+          generated function.
         """
         return lambda other: self.__operate(operator, other)
 
@@ -1475,7 +1481,7 @@ class _CompareMixin(ColumnOperators):
             return self._bind_param(other)
         else:
             return other
-    
+
     def clause_element(self):
         """Allow ``_CompareMixins`` to return the underlying ``ClauseElement``, for non-``ClauseElement`` ``_CompareMixins``."""
         return self
@@ -1496,13 +1502,12 @@ class _CompareMixin(ColumnOperators):
 
 class Selectable(ClauseElement):
     """Represent a column list-holding object.
-    
-    this is the common base class of [sqlalchemy.sql#ColumnElement]
-    and [sqlalchemy.sql#FromClause].  The reason ``ColumnElement``
-    is marked as a "list-holding" object is so that it can be treated
-    similarly to ``FromClause`` in column-selection scenarios; it 
+
+    This is the common base class of [sqlalchemy.sql#ColumnElement]
+    and [sqlalchemy.sql#FromClause].  The reason ``ColumnElement`` is
+    marked as a "list-holding" object is so that it can be treated
+    similarly to ``FromClause`` in column-selection scenarios; it
     contains a list of columns consisting of itself.
-    
     """
 
     columns = util.NotImplProperty("""a [sqlalchemy.sql#ColumnCollection] containing ``ColumnElement`` instances.""")
@@ -1511,23 +1516,22 @@ class Selectable(ClauseElement):
         return select([self], whereclauses, **params)
 
 class ColumnElement(ClauseElement, _CompareMixin):
-    """Represent an element that is useable within the 
-    "column clause" portion of a ``SELECT`` statement. 
-    
-    This includes columns associated with tables, aliases,
-    and subqueries, expressions, function calls, SQL keywords
-    such as ``NULL``, literals, etc.  ``ColumnElement`` is the 
-    ultimate base class for all such elements.
+    """Represent an element that is usable within the "column clause" portion of a ``SELECT`` statement.
+
+    This includes columns associated with tables, aliases, and
+    subqueries, expressions, function calls, SQL keywords such as
+    ``NULL``, literals, etc.  ``ColumnElement`` is the ultimate base
+    class for all such elements.
 
     ``ColumnElement`` supports the ability to be a *proxy* element,
     which indicates that the ``ColumnElement`` may be associated with
-    a ``Selectable`` which was derived from another ``Selectable``. 
-    An example of a "derived" ``Selectable`` is an ``Alias`` of 
-    ``Table``.
-    
-    a ``ColumnElement``, by subclassing the ``_CompareMixin`` mixin 
-    class, provides the ability to generate new ``ClauseElement`` 
-    objects using Python expressions.  See the ``_CompareMixin`` 
+    a ``Selectable`` which was derived from another ``Selectable``.
+    An example of a "derived" ``Selectable`` is an ``Alias`` of a
+    ``Table``.
+
+    A ``ColumnElement``, by subclassing the ``_CompareMixin`` mixin
+    class, provides the ability to generate new ``ClauseElement``
+    objects using Python expressions.  See the ``_CompareMixin``
     docstring for more details.
     """
 
@@ -1562,7 +1566,7 @@ class ColumnElement(ClauseElement, _CompareMixin):
         if len(s) == 0:
             s.add(self)
         self.__orig_set = s
-        
+
     orig_set = property(_get_orig_set, _set_orig_set,
                         doc=\
         """A Set containing TableClause-bound, non-proxied ColumnElements 
@@ -1570,10 +1574,9 @@ class ColumnElement(ClauseElement, _CompareMixin):
         for a column proxied from a Union (i.e. CompoundSelect), this 
         set will be just one element.
         """)
-    
+
     def shares_lineage(self, othercolumn):
-        """Return True if the given ``ColumnElement`` has a common
-        ancestor to this ``ColumnElement``.
+        """Return True if the given ``ColumnElement`` has a common ancestor to this ``ColumnElement``.
         """
 
         for c in self.orig_set:
@@ -1581,7 +1584,7 @@ class ColumnElement(ClauseElement, _CompareMixin):
                 return True
         else:
             return False
-    
+
     def _make_proxy(self, selectable, name=None):
         """Create a new ``ColumnElement`` representing this
         ``ColumnElement`` as it appears in the select list of a
@@ -1613,7 +1616,7 @@ class ColumnCollection(util.OrderedProperties):
 
     def __str__(self):
         return repr([str(c) for c in self])
-        
+
     def add(self, column):
         """Add a column to this collection.
 
@@ -1628,14 +1631,14 @@ class ColumnCollection(util.OrderedProperties):
             if other.name == other.key:
                 del self[other.name]
         self[column.key] = column
-    
+
     def remove(self, column):
         del self[column.key]
-        
+
     def extend(self, iter):
         for c in iter:
             self.add(c)
-            
+
     def __eq__(self, other):
         l = []
         for c in other:
@@ -1648,7 +1651,7 @@ class ColumnCollection(util.OrderedProperties):
         if not isinstance(other, basestring):
             raise exceptions.ArgumentError("__contains__ requires a string argument")
         return util.OrderedProperties.__contains__(self, other)
-        
+
     def contains_column(self, col):
         # have to use a Set here, because it will compare the identity
         # of the column, not just using "==" for comparison which will always return a
@@ -1658,7 +1661,7 @@ class ColumnCollection(util.OrderedProperties):
 class ColumnSet(util.OrderedSet):
     def contains_column(self, col):
         return col in self
-        
+
     def extend(self, cols):
         for col in cols:
             self.add(col)
@@ -1673,14 +1676,12 @@ class ColumnSet(util.OrderedSet):
                 if c.shares_lineage(local):
                     l.append(c==local)
         return and_(*l)
-            
+
 class FromClause(Selectable):
-    """Represent an element that can be used within the ``FROM``
-    clause of a ``SELECT`` statement.
-    """
+    """Represent an element that can be used within the ``FROM`` clause of a ``SELECT`` statement."""
 
     __visit_name__ = 'fromclause'
-    
+
     def __init__(self, name=None):
         self.name = name
 
@@ -1706,7 +1707,7 @@ class FromClause(Selectable):
 
     def alias(self, name=None):
         return Alias(self, name)
-      
+
     def named_with_column(self):
         """True if the name of this FromClause may be prepended to a
         column in a generated SQL statement.
@@ -1733,47 +1734,45 @@ class FromClause(Selectable):
         return ret
 
     def is_derived_from(self, fromclause):
-        """return True if this FromClause is 'derived' from the given FromClause.
-        
-        An example would be an Alias of a Table is derived from that Table."""
-        
+        """Return True if this FromClause is 'derived' from the given FromClause.
+
+        An example would be an Alias of a Table is derived from that Table.
+        """
+
         return False
-    
+
     def replace_selectable(self, old, alias):
-      """replace all occurences of FromClause 'old' with the given Alias object, returning a 
-      copy of this ``FromClause``."""
-      
+      """replace all occurences of FromClause 'old' with the given Alias object, returning a copy of this ``FromClause``."""
+
       from sqlalchemy import sql_util
       return sql_util.ClauseAdapter(alias).traverse(self, clone=True)
-      
+
     def corresponding_column(self, column, raiseerr=True, keys_ok=False, require_embedded=False):
-        """Given a ``ColumnElement``, return the exported
-        ``ColumnElement`` object from this ``Selectable`` which
-        corresponds to that original ``Column`` via a common
-        anscestor column.
-        
+        """Given a ``ColumnElement``, return the exported ``ColumnElement``
+        object from this ``Selectable`` which corresponds to that
+        original ``Column`` via a common anscestor column.
+
         column
           the target ``ColumnElement`` to be matched
-            
+
         raiseerr
-          if True, raise an error if the given ``ColumnElement``
-          could not be matched. if False, non-matches will
-          return None.
-            
+          if True, raise an error if the given ``ColumnElement`` could
+          not be matched. if False, non-matches will return None.
+
         keys_ok
-          if the ``ColumnElement`` cannot be matched, attempt to
-          match based on the string "key" property of the column
-          alone. This makes the search much more liberal.
-            
+          if the ``ColumnElement`` cannot be matched, attempt to match
+          based on the string "key" property of the column alone. This
+          makes the search much more liberal.
+
         require_embedded
           only return corresponding columns for the given
           ``ColumnElement``, if the given ``ColumnElement`` is
           actually present within a sub-element of this
-          ``FromClause``.  Normally the column will match if
-          it merely shares a common anscestor with one of
-          the exported columns of this ``FromClause``.
+          ``FromClause``.  Normally the column will match if it merely
+          shares a common anscestor with one of the exported columns
+          of this ``FromClause``.
         """
-            
+
         if self.c.contains_column(column):
             return column
 
@@ -1806,10 +1805,11 @@ class FromClause(Selectable):
             return getattr(self, name)
 
     def _clone_from_clause(self):
-        # delete all the "generated" collections of columns for a newly cloned FromClause,
-        # so that they will be re-derived from the item.
-        # this is because FromClause subclasses, when cloned, need to reestablish new "proxied" 
-        # columns that are linked to the new item
+        # delete all the "generated" collections of columns for a
+        # newly cloned FromClause, so that they will be re-derived
+        # from the item.  this is because FromClause subclasses, when
+        # cloned, need to reestablish new "proxied" columns that are
+        # linked to the new item
         for attr in ('_columns', '_primary_key' '_foreign_keys', '_orig_cols', '_oid_column'):
             if hasattr(self, attr):
                 delattr(self, attr)
@@ -1851,17 +1851,19 @@ class FromClause(Selectable):
             cp = self._proxy_column(co)
             for ci in cp.orig_set:
                 cx = self._orig_cols.get(ci)
-                # TODO: the '=' thing here relates to the order of columns as they are placed in the
-                # "columns" collection of a CompositeSelect, illustrated in test/sql/selectable.SelectableTest.testunion
-                # make this relationship less brittle
+                # TODO: the '=' thing here relates to the order of
+                # columns as they are placed in the "columns"
+                # collection of a CompositeSelect, illustrated in
+                # test/sql/selectable.SelectableTest.testunion make
+                # this relationship less brittle
                 if cx is None or cp._distance <= cx._distance:
                     self._orig_cols[ci] = cp
         if self.oid_column is not None:
             for ci in self.oid_column.orig_set:
                 self._orig_cols[ci] = self.oid_column
-    
+
     def _flatten_exportable_columns(self):
-        """return the list of ColumnElements represented within this FromClause's _exportable_columns"""
+        """Return the list of ColumnElements represented within this FromClause's _exportable_columns"""
         export = self._exportable_columns()
         for column in export:
             if isinstance(column, Selectable):
@@ -1871,7 +1873,7 @@ class FromClause(Selectable):
                 yield column
             else:
                 continue
-        
+
     def _exportable_columns(self):
         return []
 
@@ -1885,7 +1887,7 @@ class _BindParamClause(ClauseElement, _CompareMixin):
     """
 
     __visit_name__ = 'bindparam'
-    
+
     def __init__(self, key, value, shortname=None, type_=None, unique=False, isoutparam=False):
         """Construct a _BindParamClause.
 
@@ -1915,11 +1917,11 @@ class _BindParamClause(ClauseElement, _CompareMixin):
           execution time.
 
         unique
-          if True, the key name of this BindParamClause will be 
-          modified if another ``_BindParamClause`` of the same
-          name already has been located within the containing 
+          if True, the key name of this BindParamClause will be
+          modified if another ``_BindParamClause`` of the same name
+          already has been located within the containing
           ``ClauseElement``.
-          
+
         isoutparam
           if True, the parameter should be treated like a stored procedure "OUT"
           parameter.
@@ -1935,7 +1937,7 @@ class _BindParamClause(ClauseElement, _CompareMixin):
             self.type = sqltypes.to_instance(_BindParamClause.type_map[type(value)])
         else:
             self.type = type_
-    
+
     # TODO: move to types module, obviously
     type_map = {
         str : sqltypes.String,
@@ -1943,7 +1945,7 @@ class _BindParamClause(ClauseElement, _CompareMixin):
         int : sqltypes.Integer,
         float : sqltypes.Numeric
     }
-    
+
     def _get_from_objects(self, **modifiers):
         return []
 
@@ -1976,7 +1978,7 @@ class _TypeClause(ClauseElement):
     """
 
     __visit_name__ = 'typeclause'
-    
+
     def __init__(self, type):
         self.type = type
 
@@ -1990,7 +1992,7 @@ class _TextClause(ClauseElement):
     """
 
     __visit_name__ = 'textclause'
-    
+
     def __init__(self, text = "", bind=None, bindparams=None, typemap=None):
         self._bind = bind
         self.bindparams = {}
@@ -2002,7 +2004,7 @@ class _TextClause(ClauseElement):
         def repl(m):
             self.bindparams[m.group(1)] = bindparam(m.group(1))
             return ":%s" % m.group(1)
-        
+
         # scan the string and search for bind parameter names, add them
         # to the list of bindparams
         self.text = BIND_PARAMS.sub(repl, text)
@@ -2052,7 +2054,7 @@ class ClauseList(ClauseElement):
     By default, is comma-separated, such as a column listing.
     """
     __visit_name__ = 'clauselist'
-    
+
     def __init__(self, *clauses, **kwargs):
         self.clauses = []
         self.operator = kwargs.pop('operator', operators.comma_op)
@@ -2067,10 +2069,12 @@ class ClauseList(ClauseElement):
         return iter(self.clauses)
     def __len__(self):
         return len(self.clauses)
-        
+
     def append(self, clause):
-        # TODO: not sure if i like the 'group_contents' flag.  need to define the difference between
-        # a ClauseList of ClauseLists, and a "flattened" ClauseList of ClauseLists.  flatten() method ?
+        # TODO: not sure if i like the 'group_contents' flag.  need to
+        # define the difference between a ClauseList of ClauseLists,
+        # and a "flattened" ClauseList of ClauseLists.  flatten()
+        # method ?
         if self.group_contents:
             self.clauses.append(_literal_as_text(clause).self_group(against=self.operator))
         else:
@@ -2116,8 +2120,9 @@ class _CalculatedClause(ColumnElement):
     Extends ``ColumnElement`` to provide column-level comparison
     operators.
     """
+
     __visit_name__ = 'calculatedclause'
-    
+
     def __init__(self, name, *clauses, **kwargs):
         self.name = name
         self.type = sqltypes.to_instance(kwargs.get('type_', None))
@@ -2128,22 +2133,22 @@ class _CalculatedClause(ColumnElement):
             self.clause_expr = clauses.self_group()
         else:
             self.clause_expr = clauses
-            
+
     key = property(lambda self:self.name or "_calc_")
 
     def _copy_internals(self):
         self.clause_expr = self.clause_expr._clone()
-    
+
     def clauses(self):
         if isinstance(self.clause_expr, _Grouping):
             return self.clause_expr.elem
         else:
             return self.clause_expr
     clauses = property(clauses)
-        
+
     def get_children(self, **kwargs):
         return self.clause_expr,
-        
+
     def _get_from_objects(self, **modifiers):
         return self.clauses._get_from_objects(**modifiers)
 
@@ -2178,17 +2183,18 @@ class _Function(_CalculatedClause, FromClause):
 
     key = property(lambda self:self.name)
     columns = property(lambda self:[self])
-    
+
     def _copy_internals(self):
         _CalculatedClause._copy_internals(self)
         self._clone_from_clause()
 
     def get_children(self, **kwargs):
         return _CalculatedClause.get_children(self, **kwargs)
-        
+
     def append(self, clause):
         self.clauses.append(_literal_as_binds(clause, self.name))
 
+
 class _Cast(ColumnElement):
 
     def __init__(self, clause, totype, **kwargs):
@@ -2198,7 +2204,7 @@ class _Cast(ColumnElement):
         self.clause = clause
         self.typeclause = _TypeClause(self.type)
         self._distance = 0
-        
+
     def _copy_internals(self):
         self.clause = self.clause._clone()
         self.typeclause = self.typeclause._clone()
@@ -2224,11 +2230,11 @@ class _UnaryExpression(ColumnElement):
     def __init__(self, element, operator=None, modifier=None, type_=None, negate=None):
         self.operator = operator
         self.modifier = modifier
-        
+
         self.element = _literal_as_text(element).self_group(against=self.operator or self.modifier)
         self.type = sqltypes.to_instance(type_)
         self.negate = negate
-        
+
     def _get_from_objects(self, **modifiers):
         return self.element._get_from_objects(**modifiers)
 
@@ -2242,7 +2248,8 @@ class _UnaryExpression(ColumnElement):
         """Compare this ``_UnaryExpression`` against the given ``ClauseElement``."""
 
         return (
-            isinstance(other, _UnaryExpression) and self.operator == other.operator and
+            isinstance(other, _UnaryExpression) and
+            self.operator == other.operator and
             self.modifier == other.modifier and 
             self.element.compare(other.element)
         )
@@ -2252,7 +2259,7 @@ class _UnaryExpression(ColumnElement):
             return _UnaryExpression(self.element, operator=self.negate, negate=self.operator, modifier=self.modifier, type_=self.type)
         else:
             return super(_UnaryExpression, self)._negate()
-    
+
     def self_group(self, against):
         if self.operator and PRECEDENCE.get(self.operator, PRECEDENCE[_smallest]) <= PRECEDENCE.get(against, PRECEDENCE[_largest]):
             return _Grouping(self)
@@ -2262,7 +2269,7 @@ class _UnaryExpression(ColumnElement):
 
 class _BinaryExpression(ColumnElement):
     """Represent an expression that is ``LEFT <operator> RIGHT``."""
-    
+
     def __init__(self, left, right, operator, type_=None, negate=None):
         self.left = _literal_as_text(left).self_group(against=operator)
         self.right = _literal_as_text(right).self_group(against=operator)
@@ -2284,23 +2291,28 @@ class _BinaryExpression(ColumnElement):
         """Compare this ``_BinaryExpression`` against the given ``_BinaryExpression``."""
 
         return (
-            isinstance(other, _BinaryExpression) and self.operator == other.operator and
+            isinstance(other, _BinaryExpression) and
+            self.operator == other.operator and
+            (
+                self.left.compare(other.left) and
+                self.right.compare(other.right) or
                 (
-                    self.left.compare(other.left) and self.right.compare(other.right)
-                    or (
-                        self.operator in [operators.eq, operators.ne, operators.add, operators.mul] and
-                        self.left.compare(other.right) and self.right.compare(other.left)
-                    )
+                    self.operator in [operators.eq, operators.ne,
+                                      operators.add, operators.mul] and
+                    self.left.compare(other.right) and
+                    self.right.compare(other.left)
                 )
+            )
         )
-        
+
     def self_group(self, against=None):
-        # use small/large defaults for comparison so that unknown operators are always parenthesized
+        # use small/large defaults for comparison so that unknown
+        # operators are always parenthesized
         if self.operator != against and (PRECEDENCE.get(self.operator, PRECEDENCE[_smallest]) <= PRECEDENCE.get(against, PRECEDENCE[_largest])):
             return _Grouping(self)
         else:
             return self
-    
+
     def _negate(self):
         if self.negate is not None:
             return _BinaryExpression(self.left, self.right, self.negate, negate=self.operator, type_=self.type)
@@ -2309,7 +2321,7 @@ class _BinaryExpression(ColumnElement):
 
 class _Exists(_UnaryExpression):
     __visit_name__ = _UnaryExpression.__visit_name__
-    
+
     def __init__(self, *args, **kwargs):
         kwargs['correlate'] = True
         s = select(*args, **kwargs).as_scalar().self_group()
@@ -2322,24 +2334,23 @@ class _Exists(_UnaryExpression):
         e = self._clone()
         e.element = self.element.correlate(fromclause).self_group()
         return e
-    
+
     def where(self, clause):
         e = self._clone()
         e.element = self.element.where(clause).self_group()
         return e
-      
+
     def _hide_froms(self, **modifiers):
         return self._get_from_objects(**modifiers)
 
 class Join(FromClause):
-    """represent a ``JOIN`` construct between two ``FromClause``
-    elements.
-    
-    the public constructor function for ``Join`` is the module-level
+    """represent a ``JOIN`` construct between two ``FromClause`` elements.
+
+    The public constructor function for ``Join`` is the module-level
     ``join()`` function, as well as the ``join()`` method available
     off all ``FromClause`` subclasses.
-    
     """
+
     def __init__(self, left, right, onclause=None, isouter = False):
         self.left = _selectable(left)
         self.right = _selectable(right).self_group()
@@ -2350,13 +2361,13 @@ class Join(FromClause):
         self.isouter = isouter
         self.__folded_equivalents = None
         self._init_primary_key()
-        
+
     name = property(lambda s: "Join object on " + s.left.name + " " + s.right.name)
     encodedname = property(lambda s: s.name.encode('ascii', 'backslashreplace'))
 
     def _init_primary_key(self):
         pkcol = util.Set([c for c in self._flatten_exportable_columns() if c.primary_key])
-     
+
         equivs = {}
         def add_equiv(a, b):
             for x, y in ((a, b), (b, a)):
@@ -2364,18 +2375,18 @@ class Join(FromClause):
                     equivs[x].add(y)
                 else:
                     equivs[x] = util.Set([y])
-                    
+
         class BinaryVisitor(ClauseVisitor):
             def visit_binary(self, binary):
                 if binary.operator == operators.eq:
                     add_equiv(binary.left, binary.right)
         BinaryVisitor().traverse(self.onclause)
-        
+
         for col in pkcol:
             for fk in col.foreign_keys:
                 if fk.column in pkcol:
                     add_equiv(col, fk.column)
-                    
+
         omit = util.Set()
         for col in pkcol:
             p = col
@@ -2383,14 +2394,14 @@ class Join(FromClause):
                 if p.references(c) or (c.primary_key and not p.primary_key):
                     omit.add(p)
                     p = c
-            
+
         self.__primary_key = ColumnSet([c for c in self._flatten_exportable_columns() if c.primary_key and c not in omit])
 
     primary_key = property(lambda s:s.__primary_key)
 
     def self_group(self, against=None):
         return _FromGrouping(self)
-        
+
     def _locate_oid_column(self):
         return self.left.oid_column
 
@@ -2429,14 +2440,16 @@ class Join(FromClause):
                     constraints.add(fk.constraint)
                     self.foreignkey = fk.parent
         if len(crit) == 0:
-            raise exceptions.ArgumentError("Can't find any foreign key relationships "
-                                           "between '%s' and '%s'" % (primary.name, secondary.name))
+            raise exceptions.ArgumentError(
+                "Can't find any foreign key relationships "
+                "between '%s' and '%s'" % (primary.name, secondary.name))
         elif len(constraints) > 1:
-            raise exceptions.ArgumentError("Can't determine join between '%s' and '%s'; "
-                                           "tables have more than one foreign key "
-                                           "constraint relationship between them. "
-                                           "Please specify the 'onclause' of this "
-                                           "join explicitly." % (primary.name, secondary.name))
+            raise exceptions.ArgumentError(
+                "Can't determine join between '%s' and '%s'; "
+                "tables have more than one foreign key "
+                "constraint relationship between them. "
+                "Please specify the 'onclause' of this "
+                "join explicitly." % (primary.name, secondary.name))
         elif len(crit) == 1:
             return (crit[0])
         else:
@@ -2475,31 +2488,33 @@ class Join(FromClause):
 
     folded_equivalents = property(_get_folded_equivalents, doc="Returns the column list of this Join with all equivalently-named, "
                                                             "equated columns folded into one column, where 'equated' means they are "
-                                                            "equated to each other in the ON clause of this join.")    
-    
+                                                            "equated to each other in the ON clause of this join.")
+
     def select(self, whereclause = None, fold_equivalents=False, **kwargs):
         """Create a ``Select`` from this ``Join``.
-        
+
         whereclause
-          the WHERE criterion that will be sent to the ``select()`` function
-          
+          the WHERE criterion that will be sent to the ``select()``
+          function
+
         fold_equivalents
-          based on the join criterion of this ``Join``, do not include repeat
-          column names in the column list of the resulting select, for columns that
-          are calculated to be "equivalent" based on the join criterion of this
-          ``Join``. this will recursively apply to any joins directly nested by
-          this one as well.
-          
+          based on the join criterion of this ``Join``, do not include
+          repeat column names in the column list of the resulting
+          select, for columns that are calculated to be "equivalent"
+          based on the join criterion of this ``Join``. This will
+          recursively apply to any joins directly nested by this one
+          as well.
+
         \**kwargs
           all other kwargs are sent to the underlying ``select()`` function.
           See the ``select()`` module level function for details.
-          
         """
+
         if fold_equivalents:
             collist = self.folded_equivalents
         else:
             collist = [self.left, self.right]
-            
+
         return select(collist, whereclause, from_obj=[self], **kwargs)
 
     bind = property(lambda s:s.left.bind or s.right.bind)
@@ -2519,16 +2534,17 @@ class Join(FromClause):
         return [self] + self.onclause._get_from_objects(**modifiers) + self.left._get_from_objects(**modifiers) + self.right._get_from_objects(**modifiers)
 
 class Alias(FromClause):
-    """represent an alias, as typically applied to any 
-    table or sub-select within a SQL statement using the 
-    ``AS`` keyword (or without the keyword on certain databases
-    such as Oracle).
-
-    this object is constructed from the ``alias()`` module level function
-    as well as the ``alias()`` method available on all ``FromClause``
-    subclasses.
-    
+    """Represents an table or selectable alias (AS).
+
+    Represents an alias, as typically applied to any table or
+    sub-select within a SQL statement using the ``AS`` keyword (or
+    without the keyword on certain databases such as Oracle).
+
+    This object is constructed from the ``alias()`` module level
+    function as well as the ``alias()`` method available on all
+    ``FromClause`` subclasses.
     """
+
     def __init__(self, selectable, alias=None):
         baseselectable = selectable
         while isinstance(baseselectable, Alias):
@@ -2541,7 +2557,7 @@ class Alias(FromClause):
             alias = '{ANON %d %s}' % (id(self), alias or 'anon')
         self.name = alias
         self.encodedname = alias.encode('ascii', 'backslashreplace')
-        
+
     def is_derived_from(self, fromclause):
         x = self.selectable
         while True:
@@ -2584,23 +2600,23 @@ class Alias(FromClause):
         for c in self.c:
             yield c
         yield self.selectable
-        
+
     def _get_from_objects(self):
         return [self]
 
     bind = property(lambda s: s.selectable.bind)
 
 class _ColumnElementAdapter(ColumnElement):
-    """adapts a ClauseElement which may or may not be a
+    """Adapts a ClauseElement which may or may not be a
     ColumnElement subclass itself into an object which
     acts like a ColumnElement.
     """
-    
+
     def __init__(self, elem):
         self.elem = elem
         self.type = getattr(elem, 'type', None)
         self.orig_set = getattr(elem, 'orig_set', util.Set())
-        
+
     key = property(lambda s: s.elem.key)
     _label = property(lambda s: s.elem._label)
 
@@ -2620,11 +2636,11 @@ class _ColumnElementAdapter(ColumnElement):
         return getattr(self.elem, attr)
 
 class _Grouping(_ColumnElementAdapter):
-    """represent a grouping within a column expression"""
+    """Represent a grouping within a column expression"""
     pass
 
 class _FromGrouping(FromClause):
-    """represent a grouping of a FROM clause"""
+    """Represent a grouping of a FROM clause"""
     __visit_name__ = 'grouping'
 
     def __init__(self, elem):
@@ -2646,17 +2662,18 @@ class _FromGrouping(FromClause):
 
     def __getattr__(self, attr):
         return getattr(self.elem, attr)
-    
+
 class _Label(ColumnElement):
-    """represent a label, as typically applied to any column-level element
-    using the ``AS`` sql keyword.
-    
-    this object is constructed from the ``label()`` module level function
-    as well as the ``label()`` method available on all ``ColumnElement``
-    subclasses.
-    
+    """Represents a column label (AS).
+
+    Represent a label, as typically applied to any column-level
+    element using the ``AS`` sql keyword.
+
+    This object is constructed from the ``label()`` module level
+    function as well as the ``label()`` method available on all
+    ``ColumnElement`` subclasses.
     """
-    
+
     def __init__(self, name, obj, type_=None):
         while isinstance(obj, _Label):
             obj = obj.obj
@@ -2671,7 +2688,7 @@ class _Label(ColumnElement):
 
     def expression_element(self):
         return self.obj
-        
+
     def _copy_internals(self):
         self.obj = self.obj._clone()
 
@@ -2683,7 +2700,7 @@ class _Label(ColumnElement):
 
     def _hide_froms(self, **modifiers):
         return self.obj._hide_froms(**modifiers)
-        
+
     def _make_proxy(self, selectable, name = None):
         if isinstance(self.obj, (Selectable, ColumnElement)):
             return self.obj._make_proxy(selectable, name=self.name)
@@ -2692,28 +2709,29 @@ class _Label(ColumnElement):
 
 class _ColumnClause(ColumnElement):
     """Represents a generic column expression from any textual string.
+
     This includes columns associated with tables, aliases and select
-    statements, but also any arbitrary text.  May or may not be bound 
+    statements, but also any arbitrary text.  May or may not be bound
     to an underlying ``Selectable``.  ``_ColumnClause`` is usually
-    created publically via the ``column()`` function or the 
+    created publically via the ``column()`` function or the
     ``literal_column()`` function.
-    
-      text
-        the text of the element.
-        
-      selectable
-        parent selectable.
-      
-      type
-        ``TypeEngine`` object which can associate this ``_ColumnClause`` 
-        with a type.
-      
-      is_literal
-        if True, the ``_ColumnClause`` is assumed to be an exact expression
-        that will be delivered to the output with no quoting rules applied
-        regardless of case sensitive settings.  the ``literal_column()`` function is
-        usually used to create such a ``_ColumnClause``.
-    
+
+    text
+      the text of the element.
+
+    selectable
+      parent selectable.
+
+    type
+      ``TypeEngine`` object which can associate this ``_ColumnClause``
+      with a type.
+
+    is_literal
+      if True, the ``_ColumnClause`` is assumed to be an exact
+      expression that will be delivered to the output with no quoting
+      rules applied regardless of case sensitive settings.  the
+      ``literal_column()`` function is usually used to create such a
+      ``_ColumnClause``.
     """
 
     def __init__(self, text, selectable=None, type_=None, _is_oid=False, is_literal=False):
@@ -2725,20 +2743,20 @@ class _ColumnClause(ColumnElement):
         self._distance = 0
         self.__label = None
         self.is_literal = is_literal
-    
+
     def _clone(self):
         # ColumnClause is immutable
         return self
-        
+
     def _get_label(self):
         """Generate a 'label' for this column.
-        
+
         The label is a product of the parent table name and column
         name, and is treated as a unique identifier of this ``Column``
         across all ``Tables`` and derived selectables for a particular
         metadata collection.
         """
-        
+
         # for a "literal" column, we've no idea what the text is
         # therefore no 'label' can be automatically generated
         if self.is_literal:
@@ -2765,7 +2783,7 @@ class _ColumnClause(ColumnElement):
             return self
         else:
             return super(_ColumnClause, self).label(name)
-            
+
     def _get_from_objects(self, **modifiers):
         if self.table is not None:
             return [self.table]
@@ -2790,21 +2808,20 @@ class _ColumnClause(ColumnElement):
         return self.type
 
 class TableClause(FromClause):
-    """represents a "table" construct.
-    
-    Note that this represents tables only as another 
-    syntactical construct within SQL expressions; it 
-    does not provide schema-level functionality.
-    
+    """Represents a "table" construct.
+
+    Note that this represents tables only as another syntactical
+    construct within SQL expressions; it does not provide schema-level
+    functionality.
     """
-    
+
     def __init__(self, name, *columns):
         super(TableClause, self).__init__(name)
         self.name = self.fullname = name
         self.encodedname = self.name.encode('ascii', 'backslashreplace')
         self._oid_column = _ColumnClause('oid', self, _is_oid=True)
         self._export_columns(columns)
-        
+
     def _clone(self):
         # TableClause is immutable
         return self
@@ -2875,7 +2892,7 @@ class TableClause(FromClause):
     def _get_from_objects(self, **modifiers):
         return [self]
 
-    
+
 class _SelectBaseMixin(object):
     """Base class for ``Select`` and ``CompoundSelects``."""
 
@@ -2885,21 +2902,21 @@ class _SelectBaseMixin(object):
         self._limit = limit
         self._offset = offset
         self._bind = bind
-        
+
         self.append_order_by(*util.to_list(order_by, []))
         self.append_group_by(*util.to_list(group_by, []))
-    
+
     def as_scalar(self):
         return _ScalarSelect(self)
-    
+
     def apply_labels(self):
         s = self._generate()
         s.use_labels = True
         return s
-        
+
     def label(self, name):
         return self.as_scalar().label(name)
-        
+
     def supports_execution(self):
         return True
 
@@ -2907,17 +2924,17 @@ class _SelectBaseMixin(object):
         s = self._clone()
         s._clone_from_clause()
         return s
-    
+
     def limit(self, limit):
         s = self._generate()
         s._limit = limit
         return s
-    
+
     def offset(self, offset):
         s = self._generate()
         s._offset = offset
         return s
-    
+
     def order_by(self, *clauses):
         s = self._generate()
         s.append_order_by(*clauses)
@@ -2943,7 +2960,7 @@ class _SelectBaseMixin(object):
             if getattr(self, '_group_by_clause', None):
                 clauses = list(self._group_by_clause) + list(clauses)
             self._group_by_clause = ClauseList(*clauses)
-            
+
     def select(self, whereclauses = None, **params):
         return select([self], whereclauses, **params)
 
@@ -2964,7 +2981,7 @@ class _ScalarSelect(_Grouping):
         raise exceptions.InvalidRequestError("Scalar Select expression has no columns; use this object directly within a column-level expression.")
     c = property(_no_cols)
     columns = c
-    
+
     def self_group(self, **kwargs):
         return self
 
@@ -3037,7 +3054,7 @@ class CompoundSelect(_SelectBaseMixin, FromClause):
         for s in self.selects:
             for t in s._table_iterator():
                 yield t
-            
+
     def _find_engine(self):
         for s in self.selects:
             e = s._find_engine()
@@ -3047,18 +3064,20 @@ class CompoundSelect(_SelectBaseMixin, FromClause):
             return None
 
 class Select(_SelectBaseMixin, FromClause):
-    """Represent a ``SELECT`` statement, with appendable clauses, as
-    well as the ability to execute itself and return a result set.
-    
+    """Represents a ``SELECT`` statement.
+
+    Select statements support appendable clauses, as well as the
+    ability to execute themselves and return a result set.
     """
 
     def __init__(self, columns, whereclause=None, from_obj=None, distinct=False, having=None, correlate=True, prefixes=None, **kwargs):
-        """construct a Select object.
-        
-        The public constructor for Select is the [sqlalchemy.sql#select()] function; 
-        see that function for argument descriptions.
+        """Construct a Select object.
+
+        The public constructor for Select is the
+        [sqlalchemy.sql#select()] function; see that function for
+        argument descriptions.
         """
-        
+
         self._should_correlate = correlate
         self._distinct = distinct
 
@@ -3068,7 +3087,7 @@ class Select(_SelectBaseMixin, FromClause):
         self._whereclause = None
         self._having = None
         self._prefixes = []
-        
+
         if columns is not None:
             for c in columns:
                 self.append_column(c)
@@ -3079,24 +3098,28 @@ class Select(_SelectBaseMixin, FromClause):
 
         if whereclause is not None:
             self.append_whereclause(whereclause)
-            
+
         if having is not None:
             self.append_having(having)
 
+        if prefixes is not None:
+            for p in prefixes:
+                self.append_prefix(p)
+
         _SelectBaseMixin.__init__(self, **kwargs)
 
     def _get_display_froms(self, existing_froms=None):
-        """return the full list of 'from' clauses to be displayed.
-        
-        takes into account a set of existing froms which
-        may be rendered in the FROM clause of enclosing selects;
-        this Select may want to leave those absent if it is automatically
+        """Return the full list of 'from' clauses to be displayed.
+
+        Takes into account a set of existing froms which may be
+        rendered in the FROM clause of enclosing selects; this Select
+        may want to leave those absent if it is automatically
         correlating.
         """
 
         froms = util.OrderedSet()
         hide_froms = util.Set()
-        
+
         for col in self._raw_columns:
             for f in col._hide_froms():
                 hide_froms.add(f)
@@ -3106,7 +3129,7 @@ class Select(_SelectBaseMixin, FromClause):
         if self._whereclause is not None:
             for f in self._whereclause._get_from_objects(is_where=True):
                 froms.add(f)
-        
+
         for elem in self._froms:
             froms.add(elem)
             for f in elem._get_from_objects():
@@ -3117,7 +3140,7 @@ class Select(_SelectBaseMixin, FromClause):
                 hide_froms.add(f)
 
         froms = froms.difference(hide_froms)
-        
+
         if len(froms) > 1:
             corr = self.__correlate
             if self._should_correlate and existing_froms is not None:
@@ -3128,7 +3151,7 @@ class Select(_SelectBaseMixin, FromClause):
             return f
         else:
             return froms
-    
+
     froms = property(_get_display_froms, doc="""Return a list of all FromClause elements which will be applied to the FROM clause of the resulting statement.""")
 
     name = property(lambda self:"Select statement")
@@ -3142,7 +3165,7 @@ class Select(_SelectBaseMixin, FromClause):
         if self._whereclause is not None:
             for f in self._whereclause._get_from_objects(is_where=True):
                 froms.add(f)
-        
+
         for elem in self._froms:
             froms.add(elem)
             for f in elem._get_from_objects():
@@ -3156,9 +3179,9 @@ class Select(_SelectBaseMixin, FromClause):
                     yield co
             else:
                 yield c
-            
+
     inner_columns = property(_get_inner_columns)
-    
+
     def _copy_internals(self):
         self._clone_from_clause()
         self._raw_columns = [c._clone() for c in self._raw_columns]
@@ -3185,22 +3208,22 @@ class Select(_SelectBaseMixin, FromClause):
                 oldfroms.remove(old)
         self.__correlate = self.__correlate.union(newcorrelate)
         self._froms = [f for f in oldfroms.union(newfroms)]
-        
+
     def column(self, column):
         s = self._generate()
         s.append_column(column)
         return s
-    
+
     def where(self, whereclause):
         s = self._generate()
         s.append_whereclause(whereclause)
         return s
-    
+
     def having(self, having):
         s = self._generate()
         s.append_having(having)
         return s
-    
+
     def distinct(self):
         s = self._generate()
         s._distinct = True
@@ -3210,17 +3233,17 @@ class Select(_SelectBaseMixin, FromClause):
         s = self._generate()
         s.append_prefix(clause)
         return s
-        
+
     def select_from(self, fromclause):
         s = self._generate()
         s.append_from(fromclause)
         return s
-    
+
     def __dont_correlate(self):
         s = self._generate()
         s._should_correlate = False
         return s
-        
+
     def correlate(self, fromclause):
         s = self._generate()
         s._should_correlate=False
@@ -3229,10 +3252,10 @@ class Select(_SelectBaseMixin, FromClause):
         else:
             s.append_correlation(fromclause)
         return s
-    
+
     def append_correlation(self, fromclause):
         self.__correlate.add(fromclause)
-            
+
     def append_column(self, column):
         column = _literal_as_column(column)
 
@@ -3240,17 +3263,17 @@ class Select(_SelectBaseMixin, FromClause):
             column = column.self_group(against=operators.comma_op)
 
         self._raw_columns.append(column)
-    
+
     def append_prefix(self, clause):
         clause = _literal_as_text(clause)
         self._prefixes.append(clause)
-        
+
     def append_whereclause(self, whereclause):
         if self._whereclause  is not None:
             self._whereclause = and_(self._whereclause, _literal_as_text(whereclause))
         else:
             self._whereclause = _literal_as_text(whereclause)
-            
+
     def append_having(self, having):
         if self._having is not None:
             self._having = and_(self._having, _literal_as_text(having))
@@ -3264,7 +3287,7 @@ class Select(_SelectBaseMixin, FromClause):
 
     def _exportable_columns(self):
         return [c for c in self._raw_columns if isinstance(c, (Selectable, ColumnElement))]
-        
+
     def _proxy_column(self, column):
         if self.use_labels:
             return column._make_proxy(self, name=column._label)
@@ -3279,8 +3302,9 @@ class Select(_SelectBaseMixin, FromClause):
     def _locate_oid_column(self):
         for f in self.locate_all_froms():
             if f is self:
-                # we might be in our own _froms list if a column with us as the parent is attached,
-                # which includes textual columns.
+                # we might be in our own _froms list if a column with
+                # us as the parent is attached, which includes textual
+                # columns.
                 continue
             oid = f.oid_column
             if oid is not None:
@@ -3310,7 +3334,7 @@ class Select(_SelectBaseMixin, FromClause):
         for t in NoColumnVisitor().iterate(self):
             if isinstance(t, TableClause):
                 yield t
-        
+
     def _find_engine(self):
         """Try to return a Engine, either explicitly set in this
         object, or searched within the from clauses for one.
@@ -3344,11 +3368,9 @@ class _UpdateBase(ClauseElement):
 
     def _table_iterator(self):
         return iter([self.table])
-        
+
     def _process_colparams(self, parameters):
-        """Receive the *values* of an ``INSERT`` or ``UPDATE``
-        statement and construct appropriate bind parameters.
-        """
+        """Receive the *values* of an ``INSERT`` or ``UPDATE`` statement and construct appropriate bind parameters."""
 
         if parameters is None:
             return None
@@ -3404,7 +3426,7 @@ class Insert(_UpdateBase):
             u.parameters = self.parameters.copy()
             u.parameters.update(u._process_colparams(v))
         return u
-        
+
 class Update(_UpdateBase):
     def __init__(self, table, whereclause, values=None):
         self.table = table
@@ -3420,7 +3442,7 @@ class Update(_UpdateBase):
     def _copy_internals(self):
         self._whereclause = self._whereclause._clone()
         self.parameters = self.parameters.copy()
-        
+
     def values(self, v):
         if len(v) == 0:
             return self
index ab3e49f93c9c29106d848d936bf856eb10c1889d..46e0a71376c9f36957026b9c298df3906af3bc61 100644 (file)
@@ -667,7 +667,44 @@ class TypesTest(AssertMixin):
             print "Expected %s" % wanted
             print "Found %s" % got
         self.assertEqual(got, wanted)
-    
+
+
+class SQLTest(AssertMixin):
+    """Tests MySQL-dialect specific compilation."""
+
+    @testing.supported('mysql')
+    def test_precolumns(self):
+        dialect = testbase.db.dialect
+
+        def gen(distinct=None, prefixes=None):
+            kw = {}
+            if distinct is not None:
+                kw['distinct'] = distinct
+            if prefixes is not None:
+                kw['prefixes'] = prefixes
+            return str(select(['q'], **kw).compile(dialect=dialect))
+
+        self.assertEqual(gen(None), 'SELECT q')
+        self.assertEqual(gen(True), 'SELECT DISTINCT q')
+        self.assertEqual(gen(1), 'SELECT DISTINCT q')
+        self.assertEqual(gen('diSTInct'), 'SELECT DISTINCT q')
+        self.assertEqual(gen('DISTINCT'), 'SELECT DISTINCT q')
+
+        # Standard SQL
+        self.assertEqual(gen('all'), 'SELECT ALL q')
+        self.assertEqual(gen('distinctrow'), 'SELECT DISTINCTROW q')
+
+        # Interaction with MySQL prefix extensions
+        self.assertEqual(
+            gen(None, ['straight_join']),
+            'SELECT straight_join q')
+        self.assertEqual(
+            gen('all', ['HIGH_PRIORITY SQL_SMALL_RESULT']),
+            'SELECT HIGH_PRIORITY SQL_SMALL_RESULT ALL q')
+        self.assertEqual(
+            gen(True, ['high_priority', sql.text('sql_cache')]),
+            'SELECT high_priority sql_cache DISTINCT q')
+
 
 def colspec(c):
     return testbase.db.dialect.schemagenerator(