[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-10 Thread Michael Bayer


On Nov 9, 2007, at 7:16 PM, [EMAIL PROTECTED] wrote:

 huh? it dies here. r3727 or 3760 all the same, py2.5..., did remove  
 all
 *pyc


the test is committed in r3763.


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-09 Thread sdobrev

one more error in ACP, took me a day to find and separate.
it's very simple and very basic... ClauseAdapter does not work.
--
from sqlalchemy import *
from sqlalchemy.sql.util import ClauseAdapter
m = MetaData()
a=Table( 'a',m,
Column( 'id',Integer, primary_key=True),
Column( 'xxx_id', Integer, ForeignKey( 'a.id', name='adf', 
use_alter=True ) )
)

e = (a.c.id == a.c.xxx_id)
print e

b = a.alias()
#print b.c.id == 0

r = ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
).traverse( e)
print e

# results

#in r3726: (OK)
a.id = a.xxx_id
a_1.id = a.xxx_id

#in r3727 - as well as in r3760:
a.id = a.xxx_id
a.id = a.xxx_id


it does generate proper thing in ClauseAdapter.conv_element()/newcol but 
it gets lost in the way

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-09 Thread Michael Bayer


On Nov 9, 2007, at 6:49 PM, [EMAIL PROTECTED] wrote:

 om sqlalchemy import *
 from sqlalchemy.sql.util import ClauseAdapter
 m = MetaData()
 a=Table( 'a',m,
Column( 'id',Integer, primary_key=True),
Column( 'xxx_id', Integer, ForeignKey( 'a.id', name='adf',
 use_alter=True ) )
 )

 e = (a.c.id == a.c.xxx_id)
 print e

 b = a.alias()
 #print b.c.id == 0

 r = ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)
 print e

 # results

 #in r3726: (OK)
 a.id = a.xxx_id
 a_1.id = a.xxx_id

 #in r3727 - as well as in r3760:
 a.id = a.xxx_id
 a.id = a.xxx_id

no, it works, it just clones in all cases:

sql_util.ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)

assert str(e) == a_1.id = a.xxx_id



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-09 Thread sdobrev


 om sqlalchemy import *
 from sqlalchemy.sql.util import ClauseAdapter
 m = MetaData()
 a=Table( 'a',m,
Column( 'id',Integer, primary_key=True),
Column( 'xxx_id', Integer, ForeignKey( 'a.id', name='adf',
 use_alter=True ) )
 )

 e = (a.c.id == a.c.xxx_id)
 print e

 b = a.alias()
 #print b.c.id == 0

 r = ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)
 print e

 # results

 #in r3726: (OK)
 a.id = a.xxx_id
 a_1.id = a.xxx_id

 #in r3727 - as well as in r3760:
 a.id = a.xxx_id
 a.id = a.xxx_id
 

 no, it works, it just clones in all cases:

 sql_util.ClauseAdapter( b, include= set([ a.c.id ]),
 equivalents= { a.c.id: set([ a.c.id]) }
  ).traverse( e)

 assert str(e) == a_1.id = a.xxx_id
   
huh? it dies here. r3727 or 3760 all the same, py2.5..., did remove all 
*pyc


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-09 Thread Michael Bayer


On Nov 9, 2007, at 7:26 PM, Michael Bayer wrote:



 On Nov 9, 2007, at 6:49 PM, [EMAIL PROTECTED] wrote:

 om sqlalchemy import *
 from sqlalchemy.sql.util import ClauseAdapter
 m = MetaData()
 a=Table( 'a',m,
   Column( 'id',Integer, primary_key=True),
   Column( 'xxx_id', Integer, ForeignKey( 'a.id', name='adf',
 use_alter=True ) )
 )

 e = (a.c.id == a.c.xxx_id)
 print e

 b = a.alias()
 #print b.c.id == 0

 r = ClauseAdapter( b, include= set([ a.c.id ]),
   equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)
 print e

 # results

 #in r3726: (OK)
 a.id = a.xxx_id
 a_1.id = a.xxx_id

 #in r3727 - as well as in r3760:
 a.id = a.xxx_id
 a.id = a.xxx_id

 no, it works, it just clones in all cases:

 sql_util.ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)

 assert str(e) == a_1.id = a.xxx_id


oof, try again, notice the assignment:

 e = sql_util.ClauseAdapter( b, include= set([ a.c.id ]),
equivalents= { a.c.id: set([ a.c.id]) }
 ).traverse( e)
 print e
 assert str(e) == a_1.id = a.xxx_id



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread Michael Bayer


On Nov 8, 2007, at 2:01 AM, [EMAIL PROTECTED] wrote:

 i dont really understand why u need the ACP being so different to  
 plain
 visitor; i mean cant they share some skeleton part of traversing,  
 while
 putting all the choices (visit* vs convert; onentry/onexit; stop/dont)
 in their own parts.
 After all, visitor pattern is twofold,  a) Guide + b) Visitor; the  
 Guide
 doing traversing, the Visitor noting things; choice where to go  
 might be
 in visitor and/or in guide. some times (one extreme) the visitor is  
 just
 one dumb functor; other cases (other extreme end)  the visitor is very
 sofisticated and even does guiding/traversing.
 Here it looks more like second case, u have most of both sides put in
 the Visitor, and only small part (specific visit_* / copy_internals)
 left to the actual nodes.
 And to me, the skeleton is still same between ACP and ClauseVisitor.


you cant use plain visitor beacuse you are copying the whole structure  
in place at the same time, and a method is deciding arbitrarily to not  
copy certain elements, and instead returns an element that was set  
from the outside; that element cannot be mutated since its not from  
the original structure, therefore it cannot be traversed.

as it turns out, this visitor still has lots of problems which will  
continue to prevent more sophisticated copy-and-replace  
operations...some of the ways that a Select() just works from the  
ground up just get in the way here.

if you are curious why there was a rewrite, heres the test which  
needed to pass:

 metadata = MetaData()
 a = Table('a', metadata,
 Column('id', Integer, primary_key=True))
 b = Table('b', metadata,
 Column('id', Integer, primary_key=True),
 Column('aid', Integer, ForeignKey('a.id')),
 )
 c = Table('c', metadata,
 Column('id', Integer, primary_key=True),
 Column('bid', Integer, ForeignKey('b.id')),
 )

 d = Table('d', metadata,
 Column('id', Integer, primary_key=True),
 Column('aid', Integer, ForeignKey('a.id')),
 )

 j1 = a.outerjoin(b)
 j2 = select([j1], use_labels=True)

 j3 = c.join(j2, j2.c.b_id==c.c.bid)

 j4 = j3.outerjoin(d)
 self.assert_compile(j4,  c JOIN (SELECT a.id AS a_id, b.id  
AS b_id, b.aid AS b_aid FROM a LEFT OUTER JOIN b ON a.id = b.aid) 
  ON b_id = c.bid
   LEFT OUTER JOIN d ON a_id = d.aid)
 j5 = j3.alias('foo')
 j6 = sql_util.ClauseAdapter(j5).copy_and_process([j4])[0]

 # this statement takes c join(a join b), wraps it inside an  
aliased select * from c join(a join b) AS foo.
 # the outermost right side left outer join d stays the  
same, except d joins against foo.a_id instead
 # of plain a_id
 self.assert_compile(j6, (SELECT c.id AS c_id, c.bid AS  
c_bid, a_id AS a_id, b_id AS b_id, b_aid AS b_aid FROM 
 c JOIN (SELECT a.id AS a_id, b.id AS  
b_id, b.aid AS b_aid FROM a LEFT OUTER JOIN b ON a.id = b.aid) 
 ON b_id = c.bid) AS foo
  LEFT OUTER JOIN d ON foo.a_id =  
d.aid)


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread Michael Bayer


On Nov 8, 2007, at 11:32 AM, svilen wrote:


 mmmh. u can think of splitting the Visitor into 3: Guide (who
 traverses _everything_ given), Visitor (who does things), and
 intermediate Decisor, who decides where to go / what to do. But this
 can get complicated (slow) although it would be quite clear who does
 what.
 Also, do have both onEntry and onExit for each node; i am sure some
 operations will require both; first to gather info, second to make a
 decision about what to do with it while still at that level.

 i've done quite a lot of tree/expression traversers, and while
 readonly walking doesnot care much if on entry or on exit (except if
 u want depth or breadth first), replacements-in-place and
 copy+replace sometimes needed both entry and exit hooks, + they where
 conditional like in leafs.

i think you should come up with your own ACP and lets take a look at  
it.while i can get various ACP ideas to work further and further,  
im still able to come up with plenty of cases where none of them work  
and its because the structure of a clauseelement really isnt a tree.   
the same node can be represented many times largely because columns  
reference their parent table.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread sdobrev

Michael Bayer wrote:
 On Nov 8, 2007, at 11:32 AM, svilen wrote:

   
 mmmh. u can think of splitting the Visitor into 3: Guide (who
 traverses _everything_ given), Visitor (who does things), and
 intermediate Decisor, who decides where to go / what to do. But this
 can get complicated (slow) although it would be quite clear who does
 what.
 Also, do have both onEntry and onExit for each node; i am sure some
 operations will require both; first to gather info, second to make a
 decision about what to do with it while still at that level.

 i've done quite a lot of tree/expression traversers, and while
 readonly walking doesnot care much if on entry or on exit (except if
 u want depth or breadth first), replacements-in-place and
 copy+replace sometimes needed both entry and exit hooks, + they where
 conditional like in leafs.
 

 i think you should come up with your own ACP and lets take a look at  
 it.while i can get various ACP ideas to work further and further,  
 im still able to come up with plenty of cases where none of them work  
 and its because the structure of a clauseelement really isnt a tree.   
 the same node can be represented many times largely because columns  
 reference their parent table.
   
u mean a graph? mmm no.
IMO an expression is a tree of nodes, each node points to some element 
of another  space (metadata things+bindparams+...), and many nodes can 
point to same element, and eventualy many elements can hold same value 
(but be different elements - e.g. literal(1) and another literal(1) - 
not sure about whether this is usable). So traversing the (original) 
tree is one thing; what to do with the elements pointed by the nodes is 
another decision; e.g.. whether to process multiple-referred elements 
multiple times or just one, etc.

i can try... but dont rely on me too much ;-)


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread Michael Bayer


heres an entirely valid SA expression:

 subq = t2.select().alias('subq')
 s = select([t1.c.col1, subq.c.col1], from_obj=[t1, subq,  
t1.join(subq, t1.c.col1==subq.c.col2)])

the way the above works is, t1.join(subq) sends a message to the  
enclosing Select to hide t1 and subq individually in the FROM  
clause.  this is some pretty old logic but its still whats in effect  
today and it makes it easy to build up Select statements without  
worrying whats already in the FROM clause.

traversing that, we will hit subq at least twice.   r3755 makes more  
changes to accomodate the above, where it only clones subq once.   
the resulting clone still has some old subq references lying around  
though...instead of trying to make the traversal crazy so that it  
finds and exactly replaces every occurence of subq or subq- 
referencing column with the exact correct replacement, i changed  
Select so that when it constructs the FROM clause it takes into  
account the old instance of subq as well as the cloned  
version...since thats really the only place that multiple copies of  
subq really matter in the final output.



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread svilen

  i dont really understand why u need the ACP being so different to
  plain
  visitor; i mean cant they share some skeleton part of traversing,
  while
  putting all the choices (visit* vs convert; onentry/onexit;
  stop/dont) in their own parts.
  After all, visitor pattern is twofold,  a) Guide + b) Visitor;
  the Guide
  doing traversing, the Visitor noting things; choice where to go
  might be
  in visitor and/or in guide. some times (one extreme) the visitor
  is just
  one dumb functor; other cases (other extreme end)  the visitor is
  very sofisticated and even does guiding/traversing.
  Here it looks more like second case, u have most of both sides
  put in the Visitor, and only small part (specific visit_* /
  copy_internals) left to the actual nodes.
  And to me, the skeleton is still same between ACP and
  ClauseVisitor.

 you cant use plain visitor beacuse you are copying the whole
 structure in place at the same time, and a method is deciding
 arbitrarily to not copy certain elements, and instead returns an
 element that was set from the outside; that element cannot be
 mutated since its not from the original structure, therefore it
 cannot be traversed.
well this is a behavior that can be controlled - to traverse the 
originals that are to be replaced, or not; and to traverse the 
replacement AFTER it has been replaced or not.

 as it turns out, this visitor still has lots of problems which will
 continue to prevent more sophisticated copy-and-replace
 operations...some of the ways that a Select() just works from the
 ground up just get in the way here.

mmmh. u can think of splitting the Visitor into 3: Guide (who 
traverses _everything_ given), Visitor (who does things), and 
intermediate Decisor, who decides where to go / what to do. But this 
can get complicated (slow) although it would be quite clear who does 
what.
Also, do have both onEntry and onExit for each node; i am sure some 
operations will require both; first to gather info, second to make a  
decision about what to do with it while still at that level.

i've done quite a lot of tree/expression traversers, and while 
readonly walking doesnot care much if on entry or on exit (except if 
u want depth or breadth first), replacements-in-place and 
copy+replace sometimes needed both entry and exit hooks, + they where 
conditional like in leafs.

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread sdobrev


 heres the structure of:   select(from_obj=[t1, t2, t1.join(t2)])

 select +--- t1 -+
 |--- t2  |
 +--- join of t1/t2 ---+

 t2 and t1 both have two parents, and there are two paths to each of t1  
 and t2 from the head select.  so its not a tree in the strict sense.

 or another one:

 s1 = t1.select().alias('s1')
 s2 = t1.select().alias('s2')

 s3 = s1.union(s2)  (two paths to t1:  s3-s1-t1, s3-s2-t1)

 any kind of subquery which references a table at a higher level falls  
 into this category.
   
hmm. it's still a tree, just the nodes contain same things (t1). There 
are no cyclic paths to _same_ node in the expression.
like x+y+23*(x+1) --- x is used/pointed twice but the expression is 
still a tree.

is there any case where some t1 (or even subexpr) is translated once in 
one way, and then in another branch in another way? e.g. like in the 
above x+y+... first x is to be replaced with its value, but second with 
its name (say because its in round brackets - in some now-invented 
syntax of mine ).

i think there is some mixup between what the expression is, as grammar, 
and what it actualy means, and u're trying to solve/combine both in one 
thing/visitor. maybe also what it should mean _after the processing. 
While they should be all separate notions, somehow.
eh, i'm just throwing ideas / alternative view points to play with...


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-08 Thread Michael Bayer


On Nov 8, 2007, at 2:37 PM, [EMAIL PROTECTED] wrote:



 heres the structure of:   select(from_obj=[t1, t2, t1.join(t2)])

 select +--- t1 -+
|--- t2  |
+--- join of t1/t2 ---+

 t2 and t1 both have two parents, and there are two paths to each of  
 t1
 and t2 from the head select.  so its not a tree in the strict sense.

 or another one:

 s1 = t1.select().alias('s1')
 s2 = t1.select().alias('s2')

 s3 = s1.union(s2)  (two paths to t1:  s3-s1-t1, s3-s2-t1)

 any kind of subquery which references a table at a higher level falls
 into this category.

 hmm. it's still a tree, just the nodes contain same things (t1). There
 are no cyclic paths to _same_ node in the expression.

yes, there are.  select-t1 and select-join of t1/t2 - t1 .


 like x+y+23*(x+1) --- x is used/pointed twice but the expression is
 still a tree.

only if you represent it with two distinct nodes for the two  
occurences of x.  SA's expressions don't do it that way (usually).

 is there any case where some t1 (or even subexpr) is translated once  
 in
 one way, and then in another branch in another way? e.g. like in the
 above x+y+... first x is to be replaced with its value, but second  
 with
 its name (say because its in round brackets - in some now-invented
 syntax of mine ).

there arent on my end, and its true that this scenario wouldn't be  
supported with the kinds of translations im doing.


 i think there is some mixup between what the expression is, as  
 grammar,
 and what it actualy means, and u're trying to solve/combine both in  
 one
 thing/visitor. maybe also what it should mean _after the processing.
 While they should be all separate notions, somehow.
 eh, i'm just throwing ideas / alternative view points to play with...

yeah, im starting to head towards being able to support two distinct  
nodes for x but they mean the same thing.  the current trunk does a  
litle bit of that now, since the clone operation doesn't make a  
completely copied result.  i think at the end of the day, the only  
place it matters that we have x represented by three different  
objects instead of one is when Select prints out the list of FROM  
clauses (it also might matter when we render the columns clause of the  
select).





--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer


On Nov 7, 2007, at 1:02 PM, svilen wrote:


 On Wednesday 07 November 2007 19:33:22 Michael Bayer wrote:
 ohyoure *extending* abstractclauseprocessor ???

 well yes, thats
 going to change things quite a bit.  I think you should study ACP
 in its current form; what its doing now is faithfully calling
 convert_element() for *every* element in the expression, and also
 is not copying any elements before calling convert_element() -
 convert_element() always gets components from the original clause
 only.   if convert_element() returns non-None, the resulting
 element is assembled into the output, and traversal *stops* for the
 remainder of that element.  this is different behavior than it was
 before.  the reason it stops for a replaced element is because its
 assumed that the replacement value is not part of the expression
 which is being copied, and therefore should not be copied or
 processed itself.  if its that second part of the behavior thats
 breaking it for you, we can add an option to switch it off (comment
 out line 156, stop_on.add(newelem) to produce this).
 this did not change things, the column is still not traversed.
 maybe something else also has to be changed.

the traversal will hit everything except the external collections of  
columns on objects since this is usually not needed.  to change this,  
set the column_collections attribute to True on the ACP object (or  
in your class, or anywhere).  but the old version had the same option  
turned on so not sure how that would change things.


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread svilen

On Wednesday 07 November 2007 19:33:22 Michael Bayer wrote:
 ohyoure *extending* abstractclauseprocessor ??? 
 
 well yes, thats 
 going to change things quite a bit.  I think you should study ACP
 in its current form; what its doing now is faithfully calling
 convert_element() for *every* element in the expression, and also
 is not copying any elements before calling convert_element() -
 convert_element() always gets components from the original clause
 only.   if convert_element() returns non-None, the resulting
 element is assembled into the output, and traversal *stops* for the
 remainder of that element.  this is different behavior than it was
 before.  the reason it stops for a replaced element is because its
 assumed that the replacement value is not part of the expression
 which is being copied, and therefore should not be copied or
 processed itself.  if its that second part of the behavior thats
 breaking it for you, we can add an option to switch it off (comment
 out line 156, stop_on.add(newelem) to produce this).
this did not change things, the column is still not traversed. 
maybe something else also has to be changed.

i want a copy of original expression, where certain things are 
replaced by my things, and no need to go inside them - so this 
stop_on as u describe is okay... unless: what u mean remainder? that 
the returned element is not further traversed (thats ok), or the 
parent of that element is not traversed anymore (not ok)?


 this new version of ACP can locate things besides just plain Table,
 Alias and Column objects; it can locate things like Joins embedded
 in a clause which match the target selectable.

 On Nov 7, 2007, at 10:45 AM, svilen wrote:
  On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
  On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
  - something changed in the traversing (AbstractClauseProcessor
  - r3727)
  and it does not find proper things...
 
  ACP has been entirely rewritten.   if you can provide simple
  tests in the form that theyre present in test/sql/generative.py
  and/or test/sql/ selectable.py that would be helpful.  I have a
  feeling its not missing things, its just doing it slightly
  differently.
 
  http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc
 /aggregator/ (no it does not need dbcook)
  $ cd dbcook/misc/aggregator/tests
  $ PYTHONPATH=$PYTHONPATH:../.. python convertertest.py
 
  ...
  
  FAIL: count tags per movie
   File tests/convertertest.py, line 73, in
  test1_count_tags_per_movie['oid']) ...
  AssertionError: ['oid'] != ['tabl', 'oid']
  
  FAIL: count tags per movie
   File tests/convertertest.py, line 73, in
  test1_count_tags_per_movie['oid']) ...
  AssertionError: ['oid'] != ['tabl', 'oid']
 
  
  i did print the interesting elements in my
  Converter.convert_element(), and the result is that
  a) order is slightly different - which i dont care
  b) 1 item is not traversed in r3727
  e.g.
 
  r3626:
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column users.id
  Column userpics.uid
  Column userpics.state
 
  
 
  r3627:
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column tags.oid
  Column movies.id
  Column users.id
  Column userpics.uid
  Column userpics.state
 
  the 2nd tags.tabl is missing, hence the assertFails
 
  ciao
  svilen

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer

ohyoure *extending* abstractclauseprocessor ??? well yes, thats  
going to change things quite a bit.  I think you should study ACP in  
its current form; what its doing now is faithfully calling  
convert_element() for *every* element in the expression, and also is  
not copying any elements before calling convert_element() -  
convert_element() always gets components from the original clause  
only.   if convert_element() returns non-None, the resulting element  
is assembled into the output, and traversal *stops* for the remainder  
of that element.  this is different behavior than it was before.  the  
reason it stops for a replaced element is because its assumed that the  
replacement value is not part of the expression which is being copied,  
and therefore should not be copied or processed itself.  if its that  
second part of the behavior thats breaking it for you, we can add an  
option to switch it off (comment out line 156, stop_on.add(newelem) to  
produce this).

this new version of ACP can locate things besides just plain Table,  
Alias and Column objects; it can locate things like Joins embedded in  
a clause which match the target selectable.

On Nov 7, 2007, at 10:45 AM, svilen wrote:


 On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
 On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
 - something changed in the traversing (AbstractClauseProcessor -
 r3727)
 and it does not find proper things...

 ACP has been entirely rewritten.   if you can provide simple tests
 in the form that theyre present in test/sql/generative.py and/or
 test/sql/ selectable.py that would be helpful.  I have a feeling
 its not missing things, its just doing it slightly differently.

 http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/aggregator/
 (no it does not need dbcook)
 $ cd dbcook/misc/aggregator/tests
 $ PYTHONPATH=$PYTHONPATH:../.. python convertertest.py

 ...
 
 FAIL: count tags per movie
  File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']
 
 FAIL: count tags per movie
  File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']

 
 i did print the interesting elements in my
 Converter.convert_element(), and the result is that
 a) order is slightly different - which i dont care
 b) 1 item is not traversed in r3727
 e.g.
 r3626:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 
 r3627:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 the 2nd tags.tabl is missing, hence the assertFails

 ciao
 svilen

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer


On Nov 7, 2007, at 11:03 AM, svilen wrote:


 also, i put a

 class ClauseVisitor( sql_util.AbstractClauseProcessor):
def convert_element( me, e): return None
 in the beginning of the tests.sql.generative, and after ignoreing this
 or that error, here is similar thing:

 ==
 FAIL: test_correlated_select (__main__.ClauseTest)
 --
 Traceback (most recent call last):
  File sql/generative.py, line 235, in test_correlated_select
self.assert_compile(Vis().traverse(s, clone=True), SELECT * FROM
 table1 WHERE table1.col1 = table2.col1 AND table1.col2
 = :table1_col2)
  File /home/az/src/ver/sqlalchemy-trunk/test/testlib/testing.py,
 line 262, in assert_compile
self.assert_(cc == result, \n' + cc + '\n does not match \n' +
 result + ')
 AssertionError:
 'SELECT * FROM table1 WHERE table1.col1 = table2.col1'
 does not match
 'SELECT * FROM table1 WHERE table1.col1 = table2.col1 AND table1.col2
 = :table1_col2'

 here whole subexpr is gone

that would be...correct ?  replacing convert_element() to return None  
means the given clause will be copied with no changes.  the original  
clause doesnt have the extra subexpression.






 On Wednesday 07 November 2007 17:45:04 svilen wrote:
 On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
 On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
 - something changed in the traversing (AbstractClauseProcessor
 - r3727)
 and it does not find proper things...

 ACP has been entirely rewritten.   if you can provide simple
 tests in the form that theyre present in test/sql/generative.py
 and/or test/sql/ selectable.py that would be helpful.  I have a
 feeling its not missing things, its just doing it slightly
 differently.

 i did print the interesting elements in my
 Converter.convert_element(), and the result is that
 a) order is slightly different - which i dont care
 b) 1 item is not traversed in r3727
 e.g.

 r3626:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state

 

 r3627:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state

 the 2nd tags.tabl is missing, hence the assertFails

 ciao
 svilen




 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread svilen

On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
 On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
  - something changed in the traversing (AbstractClauseProcessor -
  r3727)
  and it does not find proper things...

 ACP has been entirely rewritten.   if you can provide simple tests
 in the form that theyre present in test/sql/generative.py and/or
 test/sql/ selectable.py that would be helpful.  I have a feeling
 its not missing things, its just doing it slightly differently.

http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/aggregator/
(no it does not need dbcook)
$ cd dbcook/misc/aggregator/tests
$ PYTHONPATH=$PYTHONPATH:../.. python convertertest.py

...

FAIL: count tags per movie
  File tests/convertertest.py, line 73, in 
test1_count_tags_per_movie['oid']) ...
AssertionError: ['oid'] != ['tabl', 'oid']

FAIL: count tags per movie
  File tests/convertertest.py, line 73, in 
test1_count_tags_per_movie['oid']) ...
AssertionError: ['oid'] != ['tabl', 'oid']


i did print the interesting elements in my 
Converter.convert_element(), and the result is that 
 a) order is slightly different - which i dont care
 b) 1 item is not traversed in r3727
e.g.
r3626:
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column users.id
  Column userpics.uid
  Column userpics.state

r3627:
  Column tags.tabl
  Column tags.oid
  Column movies.id
  Column tags.oid
  Column movies.id
  Column users.id
  Column userpics.uid
  Column userpics.state
the 2nd tags.tabl is missing, hence the assertFails

ciao
svilen

--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer

OK i found some more things that i think is probably screwing you up.   
will keep you posted.

On Nov 7, 2007, at 10:45 AM, svilen wrote:


 On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
 On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
 - something changed in the traversing (AbstractClauseProcessor -
 r3727)
 and it does not find proper things...

 ACP has been entirely rewritten.   if you can provide simple tests
 in the form that theyre present in test/sql/generative.py and/or
 test/sql/ selectable.py that would be helpful.  I have a feeling
 its not missing things, its just doing it slightly differently.

 http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/aggregator/
 (no it does not need dbcook)
 $ cd dbcook/misc/aggregator/tests
 $ PYTHONPATH=$PYTHONPATH:../.. python convertertest.py

 ...
 
 FAIL: count tags per movie
  File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']
 
 FAIL: count tags per movie
  File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']

 
 i did print the interesting elements in my
 Converter.convert_element(), and the result is that
 a) order is slightly different - which i dont care
 b) 1 item is not traversed in r3727
 e.g.
 r3626:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 
 r3627:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 the 2nd tags.tabl is missing, hence the assertFails

 ciao
 svilen

 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer


On Nov 7, 2007, at 1:20 PM, svilen wrote:


 ahha. so i am replacing one whole subexpr with somthing, and the
 original subexpr is not traversed inside.
 if i comment the stop_on.add(), it attempts to traverse the result
 subexpr, not the original one.
 i want the original to be traversed. Something like doing onExit
 instead of current onEntry.
 if its too hard, i can probably traverse it twice, once just marking ,
 2nd time replaceing things? i'll try

if youre replacing a subtree, why would you want to then traverse that  
part of the subtree which was replaced ?  can you see why how i have  
it working now is reasonably straightforward ?  perhaps a second call  
to ACP.traverse() should be called for those elements which were  
replaced.  also r3754 fixes the issue that aliased selects, while  
being traversed, were not being copied properly.  i still need to  
tweak the rules for aliases (alised tables, for example, remain  
immutable).



--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread sdobrev


 ahha. so i am replacing one whole subexpr with somthing, and the
 original subexpr is not traversed inside.
 if i comment the stop_on.add(), it attempts to traverse the result
 subexpr, not the original one.
 i want the original to be traversed. Something like doing onExit
 instead of current onEntry.
 if its too hard, i can probably traverse it twice, once just marking ,
 2nd time replaceing things? i'll try
 
 if youre replacing a subtree, why would you want to then traverse that  
 part of the subtree which was replaced ?  
because as i said, the needed work is onExit of the nodes, i.e. all 
room/building is traversed, now what u want to make out of it? thus i 
can traverse only once.
 can you see why how i have  
 it working now is reasonably straightforward ?  perhaps a second call  
 to ACP.traverse() should be called for those elements which were  
 replaced.
i did change my code to traverse all twice, once doing nothing, and once 
replaceing; it works. speed there is not an issue.
Still, if u can make the onEntry/onExit/both switchable, that would be 
usable. Maybe not immediately, but i'm sure once day you'll need it. 
Right now, it is onEntry, and the actual code/choice is not done 
clearly, it is spread between traverse() and _convert_element() and similar.

Has anything changed on plain ClauseVisitor? coz' i have (more 
important) other code elsewhere, which also breaks at same r3727 - it's 
today topic of digging.
   also r3754 fixes the issue that aliased selects, while  
 being traversed, were not being copied properly.  i still need to  
 tweak the rules for aliases (alised tables, for example, remain  
 immutable).
   
i dont really understand why u need the ACP being so different to plain 
visitor; i mean cant they share some skeleton part of traversing, while 
putting all the choices (visit* vs convert; onentry/onexit; stop/dont) 
in their own parts.
After all, visitor pattern is twofold,  a) Guide + b) Visitor; the Guide 
doing traversing, the Visitor noting things; choice where to go might be 
in visitor and/or in guide. some times (one extreme) the visitor is just 
one dumb functor; other cases (other extreme end)  the visitor is very 
sofisticated and even does guiding/traversing.
Here it looks more like second case, u have most of both sides put in 
the Visitor, and only small part (specific visit_* / copy_internals) 
left to the actual nodes.
And to me, the skeleton is still same between ACP and ClauseVisitor.


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---



[sqlalchemy] Re: r3727 / AbstractClauseProcessor problem

2007-11-07 Thread Michael Bayer

try out r3754.

On Nov 7, 2007, at 6:56 PM, Michael Bayer wrote:


 OK i found some more things that i think is probably screwing you up.
 will keep you posted.

 On Nov 7, 2007, at 10:45 AM, svilen wrote:


 On Wednesday 07 November 2007 16:57:08 Michael Bayer wrote:
 On Nov 7, 2007, at 2:03 AM, [EMAIL PROTECTED] wrote:
 - something changed in the traversing (AbstractClauseProcessor -
 r3727)
 and it does not find proper things...

 ACP has been entirely rewritten.   if you can provide simple tests
 in the form that theyre present in test/sql/generative.py and/or
 test/sql/ selectable.py that would be helpful.  I have a feeling
 its not missing things, its just doing it slightly differently.

 http://dbcook.svn.sourceforge.net/viewvc/dbcook/trunk/dbcook/misc/aggregator/
 (no it does not need dbcook)
 $ cd dbcook/misc/aggregator/tests
 $ PYTHONPATH=$PYTHONPATH:../.. python convertertest.py

 ...
 
 FAIL: count tags per movie
 File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']
 
 FAIL: count tags per movie
 File tests/convertertest.py, line 73, in
 test1_count_tags_per_movie['oid']) ...
 AssertionError: ['oid'] != ['tabl', 'oid']

 
 i did print the interesting elements in my
 Converter.convert_element(), and the result is that
 a) order is slightly different - which i dont care
 b) 1 item is not traversed in r3727
 e.g.
 r3626:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 
 r3627:
 Column tags.tabl
 Column tags.oid
 Column movies.id
 Column tags.oid
 Column movies.id
 Column users.id
 Column userpics.uid
 Column userpics.state
 the 2nd tags.tabl is missing, hence the assertFails

 ciao
 svilen




 


--~--~-~--~~~---~--~~
You received this message because you are subscribed to the Google Groups 
sqlalchemy group.
To post to this group, send email to sqlalchemy@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sqlalchemy?hl=en
-~--~~~~--~~--~--~---