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: T*he 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 <javascript:>> > 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 = p2bases.id UNION SELECT p2bases.id AS id, > >> p2bases.parent_id AS parent_id > >> > >> FROM p2bases, cte > >> > >> WHERE p2bases.id = cte.parent_id) > >> > >> SELECT p2bases.id AS p2bases_id, p2bases.classname AS > p2bases_classname, > >> p2bases.position AS p2bases_position, p2bases.parent_id AS > >> p2bases_parent_id, > >> cte.id AS cte_id, cte.parent_id AS cte_parent_id > >> > >> FROM p2bases, cte > >> > >> WHERE p2bases.id = %(id_1)s > >> > >> {'id_1': 1} > >> > >> > >> > >> Notice that `P2B.id == cls.id` in the cte becomes `p2bases.id = > >> p2bases.id`. > >> > >> > >> What am I missing in my @hypbrid_property.expression declaration? > >> > >> > >> How do I use my ancestors @hybrid_property.expression using > >> session.query(...)? > >> > >> ancestors = session.query(P2B.ancestors).get(a_child_id) > >> > >> > >> Example1: > >> > http://docs.sqlalchemy.org/en/latest/orm/extensions/hybrid.html#correlated-subquery-relationship-hybrid > > > > > -- > > 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.