Hmmm - makes sense. I'll switch to plain @property instead. Thank you very much again Mike!
On Tuesday, June 12, 2018 at 3:32:35 PM UTC-5, Mike Bayer wrote: > > On Tue, Jun 12, 2018 at 12:20 PM, HP3 <henddher...@gmail.com <javascript:>> > wrote: > > Hmmm > > > > In my testing, the class level functionality doesn't seem to be used > ever. > > Only the instance level. > > yup, because you can't do inspect(cls).session, that wouldn't have worked. > > hence safer to use @property so that your code does not imply it > implements the class-level functionality. > > > > > > I thought the class level functionality would be used if the > > @hybrid_property.expression was declared: In this case, it was the > recursive > > CTE that didn't get the `cls.id` "automagically" populated but it never > > worked. > > > > On Tuesday, June 12, 2018 at 10:19:35 AM UTC-5, Mike Bayer wrote: > >> > >> > >> > >> On Tue, Jun 12, 2018, 10:20 AM HP3 <henddher...@gmail.com> wrote: > >>> > >>> Hmmm > >>> > >>> I didn't use the @hybrid_property.expression for anything else so I > ended > >>> up not using it. > >>> > >>> However, I still use @hybrid_property ... wouldn't it be the same as > >>> @property? > >>> > >>> (I thought they were "pretty much" the same) > >> > >> > >> > >> They're quite different because the hybrid has behavior at the class > level > >> as well, that's the whole complexity of hybrids > >> > >> > >>> > >>> > >>> On Saturday, June 9, 2018 at 8:06:18 AM UTC-5, Mike Bayer wrote: > >>>> > >>>> That's fine but you should probably use a normal @property for that, > >>>> unless you are still making use of a separate "expression" portion. > >>>> > >>>> On Fri, Jun 8, 2018, 8:04 PM HP3 <henddher...@gmail.com> wrote: > >>>>> > >>>>> I ended up settling for this: > >>>>> > >>>>> @hybrid_property > >>>>> > >>>>> def ancestors(self): > >>>>> > >>>>> session = inspect(self).session > >>>>> > >>>>> cte = session.query(P2B) \ > >>>>> > >>>>> .filter(P2B.id == self.id) \ > >>>>> > >>>>> .cte(name='cte', recursive=True) > >>>>> > >>>>> cte = cte.union( > >>>>> > >>>>> session.query(P2B) > >>>>> > >>>>> .filter(P2B.id == cte.c.parent_id) > >>>>> > >>>>> ) > >>>>> > >>>>> return session.query(cte).all() > >>>>> > >>>>> > >>>>> And each time I call child.ancestors, the SQL CTE RECURSIVE is > issued > >>>>> (of course!?) > >>>>> > >>>>> Thanks again for all your help Mike! > >>>>> > >>>>> On Friday, June 8, 2018 at 6:39:05 PM UTC-5, HP3 wrote: > >>>>>> > >>>>>> BTW, the solution of `.params(child_id=child_id)` you provided > worked > >>>>>> perfectly - forgot to mentioned earlier. > >>>>>> It issued the recursive CTE I wanted. > >>>>>> > >>>>>> I still need to ponder if I can simply live with a plain > >>>>>> select().cte() within a vanilla method or @hybrid_property or > >>>>>> @hybrid_method, all except @hybrid_property.expression as in the > latter the > >>>>>> "caller" would need to remember to bind `child_id` explicitly and > forfeit > >>>>>> the usage of `filter(ancs.c.id==child_id)` > >>>>>> > >>>>>> Thank you very much again Mike !!!! > >>>>>> > >>>>>> On Friday, June 8, 2018 at 6:06:54 PM UTC-5, Mike Bayer wrote: > >>>>>>> > >>>>>>> On Fri, Jun 8, 2018 at 6:59 PM, HP3 <henddher...@gmail.com> > wrote: > >>>>>>> > :( > >>>>>>> > > >>>>>>> > Basically, I was trying to prevent the SQL Select for each > >>>>>>> > child-to-parent > >>>>>>> > loop-iteration when navigating the tree from leaf to root > because I > >>>>>>> > figured > >>>>>>> > I could use CTE recursive as @hybrid_property.expression. > >>>>>>> > > >>>>>>> > I was trying to take full advantage of > @hybrid_property.expression > >>>>>>> > like the > >>>>>>> > examples in > >>>>>>> > > >>>>>>> > > http://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html#join-dependent-relationship-hybrid > > >>>>>>> > and > >>>>>>> > > >>>>>>> > > http://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html#module-sqlalchemy.ext.hybrid > > >>>>>>> > The examples show that self/cls is magically chosen depending on > >>>>>>> > the > >>>>>>> > context. > >>>>>>> > > >>>>>>> > Seems like I will end up having *limited* functionality for my > >>>>>>> > `@hybrid_property.expression` as I would have to pass the extra > >>>>>>> > param > >>>>>>> > `cls_id` explicitly. > >>>>>>> > > >>>>>>> > I was hoping that > >>>>>>> > `dbsession.query(P2B.ancestors).filter(P2B.id==mychildid)` > >>>>>>> > would automagically bind 'mychildid' to `cls.id` within the > >>>>>>> > @ancestors.expression. > >>>>>>> > Perhaps such is possible some other way? > >>>>>>> > >>>>>>> a hybrid is just a function to give you a component of SQL. if > you > >>>>>>> want to change the inside of it, then you need to send a parameter > on > >>>>>>> the inside or do a transformation of it. I guess you could run a > >>>>>>> transform, which is what the lazy loader does, e.g. looks for > where > >>>>>>> something like "cls.id" is and then replaces it but this is very > >>>>>>> specialized, it wouldn't look any nicer from the calling point of > >>>>>>> view. > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > >>>>>>> > > >>>>>>> > Another catch is that by issuing the manual CTE, the session > would > >>>>>>> > always > >>>>>>> > issue the SQL and never returned previously loaded ancestors. > >>>>>>> > > >>>>>>> > root > >>>>>>> > / \ > >>>>>>> > c1 c2 > >>>>>>> > > >>>>>>> > c1.ancestors and c2.ancestors will each issue SQL recursive CTE > ... > >>>>>>> > right? > >>>>>>> > > >>>>>>> > > >>>>>>> > On Friday, June 8, 2018 at 5:33:08 PM UTC-5, Mike Bayer wrote: > >>>>>>> >> > >>>>>>> >> On Fri, Jun 8, 2018 at 5:14 PM, HP3 <henddher...@gmail.com> > wrote: > >>>>>>> >> > Thank you so much Mike > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > I am trying to write @ancestors.expression to produce a SQL > like > >>>>>>> >> > this: > >>>>>>> >> > > >>>>>>> >> > WITH RECURSIVE scte(id, parent_id) AS > >>>>>>> >> > > >>>>>>> >> > (SELECT p2bases.id AS id, p2bases.parent_id AS parent_id > >>>>>>> >> > > >>>>>>> >> > FROM p2bases > >>>>>>> >> > > >>>>>>> >> > WHERE p2bases.id = %(id_1)s --- This is the param I need at > >>>>>>> >> > runtime > >>>>>>> >> > (cls.id) > >>>>>>> >> > > >>>>>>> >> > UNION SELECT p2bases.id AS id, p2bases.parent_id AS > parent_id > >>>>>>> >> > > >>>>>>> >> > FROM p2bases, scte > >>>>>>> >> > > >>>>>>> >> > WHERE p2bases.id = scte.parent_id) > >>>>>>> >> > > >>>>>>> >> > SELECT scte.id > >>>>>>> >> > > >>>>>>> >> > FROM scte > >>>>>>> >> > >>>>>>> >> > >>>>>>> >> you'd have to put the parameter inside the CTE then, here's one > >>>>>>> >> way: > >>>>>>> >> > >>>>>>> >> @ancestors.expression > >>>>>>> >> def ancestors(cls): > >>>>>>> >> cte = select([P2B.id, P2B.parent_id]) \ > >>>>>>> >> .where(P2B.id == bindparam("cls_id")) \ > >>>>>>> >> .cte(name='cte', recursive=True) > >>>>>>> >> cte = cte.union( > >>>>>>> >> select([P2B.id, P2B.parent_id]) > >>>>>>> >> .where(P2B.id == cte.c.parent_id) > >>>>>>> >> ) > >>>>>>> >> return cte > >>>>>>> >> > >>>>>>> >> > >>>>>>> >> then you do: > >>>>>>> >> > >>>>>>> >> > dbsession.query(P2B.ancestors).params(cls_id=child_id).all() > >>>>>>> >> > >>>>>>> >> > >>>>>>> >> but note that you always need to provide params(cls_id=x) in > that > >>>>>>> >> case. > >>>>>>> >> > >>>>>>> >> > >>>>>>> >> > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > Here is the @hybrid_property.expression > >>>>>>> >> > > >>>>>>> >> > @ancestors.expression > >>>>>>> >> > > >>>>>>> >> > def ancestors(cls): > >>>>>>> >> > > >>>>>>> >> > cte = select([P2B.id, P2B.parent_id]) \ > >>>>>>> >> > > >>>>>>> >> > .where(P2B.id == cls.id) \ # <<<<<<< I cannot > figure > >>>>>>> >> > out how > >>>>>>> >> > make cls.id the param > >>>>>>> >> > > >>>>>>> >> > .cte(name='cte', recursive=True) > >>>>>>> >> > > >>>>>>> >> > cte = cte.union( > >>>>>>> >> > > >>>>>>> >> > select([P2B.id, P2B.parent_id]) > >>>>>>> >> > > >>>>>>> >> > .where(P2B.id == cte.c.parent_id) > >>>>>>> >> > > >>>>>>> >> > ) > >>>>>>> >> > > >>>>>>> >> > return cte > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > I tried alias, aliased and bindparam in multiple ways > >>>>>>> >> > unsuccessfully. > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > The SQL that is coming out doesn't set the first (cte anchor) > >>>>>>> >> > WHERE > >>>>>>> >> > clause > >>>>>>> >> > with the bound param id_1 (cls.id in the > @ancestors.expression). > >>>>>>> >> > Instead, is the column again? > >>>>>>> >> > > >>>>>>> >> > WITH RECURSIVE cte(id, parent_id) AS > >>>>>>> >> > > >>>>>>> >> > (SELECT p2bases.id AS id, p2bases.parent_id AS parent_id > >>>>>>> >> > > >>>>>>> >> > FROM p2bases > >>>>>>> >> > > >>>>>>> >> > WHERE p2bases.id = p2bases.id -- <<<< I can't figure out how > to > >>>>>>> >> > make > >>>>>>> >> > expr.left 'cls.id' from the @ancestors.expression > >>>>>>> >> > > >>>>>>> >> > UNION SELECT p2bases.id AS id, p2bases.parent_id AS > parent_id > >>>>>>> >> > > >>>>>>> >> > FROM p2bases, cte > >>>>>>> >> > > >>>>>>> >> > WHERE p2bases.id = cte.parent_id) > >>>>>>> >> > > >>>>>>> >> > SELECT cte.id AS cte_id, cte.parent_id AS cte_parent_id > >>>>>>> >> > > >>>>>>> >> > FROM cte > >>>>>>> >> > > >>>>>>> >> > WHERE cte.id = %(id_1)s > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > The correct SQL comes out when I do this: > >>>>>>> >> > > >>>>>>> >> > scte = select([P2B.id, P2B.parent_id]) \ > >>>>>>> >> > > >>>>>>> >> > .where(P2B.id == child_id) \ > >>>>>>> >> > > >>>>>>> >> > .cte(name='scte', recursive=True) > >>>>>>> >> > > >>>>>>> >> > scte = scte.union( > >>>>>>> >> > > >>>>>>> >> > select([P2B.id, P2B.parent_id]).where(P2B.id == > >>>>>>> >> > scte.c.parent_id)) > >>>>>>> >> > > >>>>>>> >> > s = select([scte.c.id]) > >>>>>>> >> > > >>>>>>> >> > ancestors = dbsession.execute(s).fetchall() > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > But I don't know how to integrate that into my > >>>>>>> >> > @ancestors.expression > >>>>>>> >> > > >>>>>>> >> > I want `child_id` to get the value of `cls.id` when the > >>>>>>> >> > @hybrid_property > >>>>>>> >> > is > >>>>>>> >> > called for the class. > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > > >>>>>>> >> > On Friday, June 8, 2018 at 1:48:55 PM UTC-5, Mike Bayer > wrote: > >>>>>>> >> >> > >>>>>>> >> >> the example is huge can you point out which two queries > you'd > >>>>>>> >> >> like to > >>>>>>> >> >> compare? > >>>>>>> >> >> > >>>>>>> >> >> this: > >>>>>>> >> >> cte = dbsession.query(P2B.id, P2B.parent_id) \ > >>>>>>> >> >> .filter(P2B.id == child_id) \ > >>>>>>> >> >> .cte(name='cte', recursive=True) > >>>>>>> >> >> cte = cte.union( > >>>>>>> >> >> dbsession.query(P2B.id, P2B.parent_id).filter( > >>>>>>> >> >> P2B.id == cte.c.parent_id)) > >>>>>>> >> >> cteids = dbsession.query(cte.c.id) > >>>>>>> >> >> ancestors = > >>>>>>> >> >> dbsession.query(P2B).filter(P2B.id.in_(cteids)).all()[1:] > >>>>>>> >> >> > >>>>>>> >> >> > >>>>>>> >> >> and this? > >>>>>>> >> >> > >>>>>>> >> >> ancestors = dbsession.query( > >>>>>>> >> >> P2B.ancestors).filter(P2B.id == child_id).all() > # > >>>>>>> >> >> <<<< > >>>>>>> >> >> child_id IS NEVER USED IN EXPRESSION > >>>>>>> >> >> > >>>>>>> >> >> > >>>>>>> >> >> > >>>>>>> >> >> it might surprise you to know I barely follow what these > >>>>>>> >> >> queries are > >>>>>>> >> >> returning for you, I just look very briefly to get the > desired > >>>>>>> >> >> syntax > >>>>>>> >> >> right, so a simple "here's teh code hre's the SQL" is best > >>>>>>> >> >> > >>>>>>> >> >> > >>>>>>> >> >> > >>>>>>> >> >> On Fri, Jun 8, 2018 at 2:44 PM, HP3 <henddher...@gmail.com> > >>>>>>> >> >> wrote: > >>>>>>> >> >> > Ahhhh!!! Makes perfect sense! > >>>>>>> >> >> > > >>>>>>> >> >> > But there is something still amiss ... > >>>>>>> >> >> > The last 2 assertions are triggering because the query is > >>>>>>> >> >> > returning a > >>>>>>> >> >> > single > >>>>>>> >> >> > ancestor (self) instead of the whole recursive list. > >>>>>>> >> >> > > >>>>>>> >> >> > See the plain CTE and the @hybrid_property.expression CTE: > >>>>>>> >> >> > The where > >>>>>>> >> >> > clauses > >>>>>>> >> >> > are still different :( > >>>>>>> >> >> > (and hence the output) > >>>>>>> >> >> > > >>>>>>> >> >> > Are my @hybrid_property.expressions incorrectly declared? > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > CTE ---------------------------------------- > >>>>>>> >> >> > > >>>>>>> >> >> > 2018-06-08 13:14:44,144 INFO sqlalchemy.engine.base.Engine > >>>>>>> >> >> > BEGIN > >>>>>>> >> >> > (implicit) > >>>>>>> >> >> > > >>>>>>> >> >> > 2018-06-08 13:14:44,145 INFO sqlalchemy.engine.base.Engine > >>>>>>> >> >> > WITH > >>>>>>> >> >> > RECURSIVE > >>>>>>> >> >> > cte(id, parent_id) AS > >>>>>>> >> >> > > >>>>>>> >> >> > (SELECT p2bases.id AS id, p2bases.parent_id AS parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM p2bases > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE p2bases.id = %(id_1)s UNION SELECT p2bases.id AS > >>>>>>> >> >> > p2bases_id, > >>>>>>> >> >> > p2bases.parent_id AS p2bases_parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM p2bases, cte > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE p2bases.id = cte.parent_id) > >>>>>>> >> >> > > >>>>>>> >> >> > SELECT p2bases.id AS p2bases_id, p2bases.uuid AS > >>>>>>> >> >> > p2bases_uuid, > >>>>>>> >> >> > p2bases.classname AS p2bases_classname, p2bases.position > AS > >>>>>>> >> >> > p2bases_position, p2bases.extras AS p2bases_extras, > >>>>>>> >> >> > p2bases.val AS > >>>>>>> >> >> > p2bases_val, p2bases.time AS p2bases_time, > p2bases.parent_id > >>>>>>> >> >> > AS > >>>>>>> >> >> > p2bases_parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM p2bases > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE p2bases.id IN (SELECT cte.id AS cte_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM cte) > >>>>>>> >> >> > > >>>>>>> >> >> > 2018-06-08 13:14:44,146 INFO sqlalchemy.engine.base.Engine > >>>>>>> >> >> > {'id_1': > >>>>>>> >> >> > 20} > >>>>>>> >> >> > > >>>>>>> >> >> > CTE ANCESTORS <__main__.P2Pg object at 0x10bf94be0> > >>>>>>> >> >> > > >>>>>>> >> >> > CTE ANCESTORS <__main__.P2An object at 0x10bf9a160> > >>>>>>> >> >> > > >>>>>>> >> >> > CTE ANCESTORS <__main__.P2KVP object at 0x10bf9a6a0> > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > @hybrid_property.expression ANCESTORS CLS > >>>>>>> >> >> > ---------------------------------------- > >>>>>>> >> >> > > >>>>>>> >> >> > 2018-06-08 13:14:44,181 INFO sqlalchemy.engine.base.Engine > >>>>>>> >> >> > WITH > >>>>>>> >> >> > RECURSIVE > >>>>>>> >> >> > cte(id, parent_id) AS > >>>>>>> >> >> > > >>>>>>> >> >> > (SELECT p2bases.id AS id, p2bases.parent_id AS parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM p2bases > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE p2bases.id = p2bases.id UNION SELECT p2bases.id AS > id, > >>>>>>> >> >> > p2bases.parent_id AS parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM p2bases, cte > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE p2bases.id = cte.parent_id) > >>>>>>> >> >> > > >>>>>>> >> >> > SELECT cte.id AS cte_id, cte.parent_id AS cte_parent_id > >>>>>>> >> >> > > >>>>>>> >> >> > FROM cte > >>>>>>> >> >> > > >>>>>>> >> >> > WHERE cte.id = %(id_1)s > >>>>>>> >> >> > > >>>>>>> >> >> > 2018-06-08 13:14:44,182 INFO sqlalchemy.engine.base.Engine > >>>>>>> >> >> > {'id_1': > >>>>>>> >> >> > 20} > >>>>>>> >> >> > > >>>>>>> >> >> > @hybrid_property.expression ANCESTORS CLS (20, 5) > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > > >>>>>>> >> >> > On Friday, June 8, 2018 at 12:27:28 PM UTC-5, Mike Bayer > >>>>>>> >> >> > wrote: > >>>>>>> >> >> >> > >>>>>>> >> >> >> On Fri, Jun 8, 2018 at 12:16 PM, HP3 < > henddher...@gmail.com> > >>>>>>> >> >> >> wrote: > >>>>>>> >> >> >> > Attached the whole file > >>>>>>> >> >> >> > >>>>>>> >> >> >> OK, removing all the "zope" stuff as well as all the > other > >>>>>>> >> >> >> queries > >>>>>>> >> >> >> that aren't noted as failing, I am only looking at this > >>>>>>> >> >> >> query: > >>>>>>> >> >> >> > >>>>>>> >> >> >> ancestors = > dbsession.query(P2B.ancestors).filter(P2B.id > >>>>>>> >> >> >> == > >>>>>>> >> >> >> child_id).all() # <<<< child_id IS NEVER USED IN > EXPRESSION > >>>>>>> >> >> >> > >>>>>>> >> >> >> the problem is that you are re-introducing P2B a second > >>>>>>> >> >> >> time, rather > >>>>>>> >> >> >> than referring to the columns that your CTE returns, it > >>>>>>> >> >> >> should be: > >>>>>>> >> >> >> > >>>>>>> >> >> >> ansc = P2B.ancestors > >>>>>>> >> >> >> ancestors = dbsession.query(ansc).filter(ansc.c.id > == > >>>>>>> >> >> >> child_id).all() > >>>>>>> >> >> >> > >>>>>>> >> >> >> this produces SQL that obeys the same form I see at > >>>>>>> >> >> >> > >>>>>>> >> >> >> > https://www.postgresql.org/docs/current/static/queries-with.html. > >>>>>>> >> >> >> > >>>>>>> >> >> >> Since P2B.ancestors produces a new selectable each time, > you > >>>>>>> >> >> >> need to > >>>>>>> >> >> >> assign it to a variable in order to refer to its set of > >>>>>>> >> >> >> columns > >>>>>>> >> >> >> without re-introducing it. > >>>>>>> >> >> >> > >>>>>>> >> >> >> > >>>>>>> >> >> >> > >>>>>>> >> >> >> > >>>>>>> >> >> >> > > >>>>>>> >> >> >> > > >>>>>>> >> >> >> > On Thursday, June 7, 2018 at 7:01:21 PM UTC-5, HP3 > wrote: > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> Hello > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> Having difficulty with CTE and > >>>>>>> >> >> >> >> @hybrid_property.expression on a > >>>>>>> >> >> >> >> adjacency > >>>>>>> >> >> >> >> list model. > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> class P2B(Base): > >>>>>>> >> >> >> >> __tablename__ = 'p2bases' > >>>>>>> >> >> >> >> id = Column(Integer, primary_key=True) > >>>>>>> >> >> >> >> classname = Column(String) > >>>>>>> >> >> >> >> parent_id = Column( > >>>>>>> >> >> >> >> Integer, > >>>>>>> >> >> >> >> ForeignKey('p2bases.id', ondelete='CASCADE'), > >>>>>>> >> >> >> >> index=True > >>>>>>> >> >> >> >> ) > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> parent = relationship( > >>>>>>> >> >> >> >> 'P2B', > >>>>>>> >> >> >> >> primaryjoin='P2B.parent_id == P2B.id', > >>>>>>> >> >> >> >> foreign_keys='P2B.id', > >>>>>>> >> >> >> >> uselist=False > >>>>>>> >> >> >> >> ) > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> __mapper_args__ = { > >>>>>>> >> >> >> >> 'polymorphic_identity': 'P2B', > >>>>>>> >> >> >> >> 'polymorphic_on': classname > >>>>>>> >> >> >> >> } > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> @hybrid_property > >>>>>>> >> >> >> >> def ancestors(self): > >>>>>>> >> >> >> >> _ancestors = [] > >>>>>>> >> >> >> >> parent = self.parent > >>>>>>> >> >> >> >> while parent is not None: > >>>>>>> >> >> >> >> _ancestors.append(parent) > >>>>>>> >> >> >> >> parent = parent.parent > >>>>>>> >> >> >> >> return _ancestors > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> @ancestors.expression > >>>>>>> >> >> >> >> def ancestors(cls): > >>>>>>> >> >> >> >> cte = select([P2B.id, P2B.parent_id]) \ > >>>>>>> >> >> >> >> .where(P2B.id == cls.id) \ # <<<<<< > Based on > >>>>>>> >> >> >> >> Example1 > >>>>>>> >> >> >> >> .cte(name='cte', recursive=True) > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> cte = cte.union( > >>>>>>> >> >> >> >> select([P2B.id, P2B.parent_id]) > >>>>>>> >> >> >> >> .where(P2B.id == cte.c.parent_id) > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> ) > >>>>>>> >> >> >> >> return cte > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> The issue I am facing is that the SQL statement for > >>>>>>> >> >> >> >> ancestors > >>>>>>> >> >> >> >> expression > >>>>>>> >> >> >> >> becomes this > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> WITH RECURSIVE cte(id, parent_id) AS > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> (SELECT p2bases.id AS id, p2bases.parent_id AS > parent_id > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> FROM p2bases > >>>>>>> >> >> >> >> > >>>>>>> >> >> >> >> WHERE p2bases.id = <a href="http://p2bases.id" > >>>>>>> >> >> >> >> target="_blank" rel="nofollow" > >>>>>>> >> >> >> >> onmousedown="this.href=' > http://www.google.com/url?q\x3dhttp%3A%2F%2Fp2bases.id\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQjCNFXb6853cCgweqpw68fbajiKFHNJg';return > > <http://www.google.com/url?q%5Cx3dhttp%3A%2F%2Fp2bases.id%5Cx26sa%5Cx3dD%5Cx26sntz%5Cx3d1%5Cx26usg%5Cx3dAFQjCNFXb6853cCgweqpw68fbajiKFHNJg';return> > > >>>>>>> >> >> >> >> true;" > >>>>>>> >> >> >> >> onclick="this.href=' > http://www.google.com/url?q\x3dhttp%3A%2F%2Fp2bases.id\x26sa\x3dD\x26sntz\x3d1\x26usg\x3dAFQj > > <http://www.google.com/url?q%5Cx3dhttp%3A%2F%2Fp2bases.id%5Cx26sa%5Cx3dD%5Cx26sntz%5Cx3d1%5Cx26usg%5Cx3dAFQj> > > >>>>> > >>>>> -- > >>>>> 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 sqlalchemy+...@googlegroups.com. > >>>>> To post to this group, send email to sqlal...@googlegroups.com. > >>>>> 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 sqlalchemy+...@googlegroups.com. > >>> To post to this group, send email to sqlal...@googlegroups.com. > >>> 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 sqlalchemy+...@googlegroups.com <javascript:>. > > To post to this group, send email to sqlal...@googlegroups.com > <javascript:>. > > 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 sqlalchemy+unsubscr...@googlegroups.com. To post to this group, send email to sqlalchemy@googlegroups.com. Visit this group at https://groups.google.com/group/sqlalchemy. For more options, visit https://groups.google.com/d/optout.