Let's have two SQLAlchemy models:
class Child(Base):
__tablename__ = "child"
id = Column(String, primary_key=True)
parent_id = Column(String, ForeignKey("parent.id"), nullable=False)
class Parent(Base):
__tablename__ = "parent"
id = Column(String, primary_key=True)
children = relationship("Child", lazy="joined")
What I try to achieve is having a boolean attribute (let's call it has_deps) on Parent which will be True when there are children for a given parent.
I have also some constraints:
- It must be accessible when I convert the object to a dict
- It must not generate a correlated subquery
I tried different methods :
- Using
column_propertywithexistsgave me a correlated subquery
Parent.has_deps = column_property(
exists([Child.parent_id]).where(Child.parent_id == Parent.id)
)
results in :
SELECT parent.id AS parent_id, EXISTS (SELECT child.parent_id FROM child WHERE child.parent_id = parent.id) AS anon_1, parent.id AS id_1, child_1.id AS child_1_id, child_1.parent_id AS child_1_parent_id
FROM parent LEFT OUTER JOIN child AS child_1 ON parent.id = child_1.parent_id
- Using an
hybrid_propertyis not loaded at query time nor accessible with dict and has no purpose for that
@has_deps.expression
def has_deps(cls):
return case([(Child.parent_id != None, True)], else_=False)
(will not even be linked to the left outer alias join generated by the relationship)
As an example, this is the query I want the ORM to produce by just doing session.query(Parent).all():
SELECT parent.id AS parent_id, CASE WHEN child_1.parent_id IS NOT NULL THEN true ELSE false END AS has_deps, parent.id AS id_1, child_1.id AS child_1_id, child_1.parent_id AS child_1_parent_id
FROM parent LEFT OUTER JOIN child AS child_1 ON parent.id = child_1.parent_id