On Wed, May 9, 2018 at 3:28 AM, Zac Goldstein <[email protected]> wrote:
> I'm trying to use ClauseAdapter.traverse similar to how it's used in your
> old blog post to substitute columns in arbitrary clauses with columns on a
> different selectable that share an ancestor:
> http://techspot.zzzeek.org/archive/2008/01/1/
>
> Even in a simple case using a BinaryExpression,
> ClauseAdapter(selectable).traverse(binaryexpression) is simply returning the
> expression.  When I looked at it with the debugger, it seems the expression
> isn't being traversed, but rather it eventually feeds the entire
> BinaryExpression object into corresponding_column and subsequently returns
> the full expression since obviously the BinaryExpression can't be matched to
> a particular column on the selectable.

Here is a demonstration of ClauseAdapter traverse:

from sqlalchemy import Table, Integer, MetaData, Column, select
from sqlalchemy.sql.util import ClauseAdapter

t1 = Table(
    't1', MetaData(),
    Column('a', Integer),
    Column('b', Integer)
)

t1_alias = t1.alias()

binary_expr = t1.c.a == t1.c.b

modified = ClauseAdapter(t1_alias).traverse(binary_expr)


print(select([t1_alias]).where(binary_expr))
print(select([t1_alias]).where(modified))


in the first case, not modified, we get:

SELECT t1_1.a, t1_1.b
FROM t1 AS t1_1, t1
WHERE t1.a = t1.b


in the second, it's been modified:

SELECT t1_1.a, t1_1.b
FROM t1 AS t1_1
WHERE t1_1.a = t1_1.b

feel free to provide an MCVE that shows what's not working.

Otherwise, if you're looking for general purpose traversal with
modification, you want to use one of the two visit functions:

cloned_traverse:
https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/sql/visitors.py#L280

replacement_traverse:
https://github.com/zzzeek/sqlalchemy/blob/master/lib/sqlalchemy/sql/visitors.py#L304

replacement takes a function that will be presented with every
element, which you have the option of returning a new one to replace
it.   cloned makes use of a dictionary of visit functions, e.g.
{"binary": my_visit_binary, "column": my_visit_column, ...} where your
visitor can manipulate the state of the object given assuming it's a
"mutable" structure like a BinaryExpression (e.g. not a Column or
Table).



>
> selectable.corresponding_column(binaryexpression.left) returns the correct
> column, however ClauseAdapter(selectable).traverse(binaryexpression.left)
> does not.

can't reproduce that either:

assert binary_expr.left is t1.c.a  # not modified

# modified
assert ClauseAdapter(t1_alias).traverse(binary_expr.left) is t1_alias.c.a



# The discrepancy is found in corresponding_column being called
> with require_embedded=True during traverse, which is hardcoded.  I don't
> know if this behavior causes the behavior I previously described with the
> BinaryExpression being passed to corresponding_column, but it seemed
> noteworthy.
>
> Any ideas for fixes or alternatives?
>
> Thanks
>
>
>
> --
> SQLAlchemy -
> The Python SQL Toolkit and Object Relational Mapper
>
> http://www.sqlalchemy.org/
>
> To post example code, please provide an MCVE: Minimal, Complete, and
> Verifiable Example. See http://stackoverflow.com/help/mcve for a full
> description.
> ---
> You received this message because you are subscribed to the Google Groups
> "sqlalchemy" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at https://groups.google.com/group/sqlalchemy.
> For more options, visit https://groups.google.com/d/optout.

-- 
SQLAlchemy - 
The Python SQL Toolkit and Object Relational Mapper

http://www.sqlalchemy.org/

To post example code, please provide an MCVE: Minimal, Complete, and Verifiable 
Example.  See  http://stackoverflow.com/help/mcve for a full description.
--- 
You received this message because you are subscribed to the Google Groups 
"sqlalchemy" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sqlalchemy.
For more options, visit https://groups.google.com/d/optout.

Reply via email to