在 SQLAlchemy 的 hybrid_property 中使用(加入和选择)Postgres CTE

Using (joining and selecting from) an Postgres CTE in SQLAlchemy's hybrid_property

我将一个 Postgres 函数加载到数据库中,该函数使用两个参数来获取一些数据。我正在尝试使用 SQLAlchemy 的 hybrid_property.expression 来访问并使其在生成的 select.

中可用

这是函数的header:

CREATE OR REPLACE FUNCTION the_func(int, character varying)
RETURNS TABLE (
  mymodel_id int,
  x_const character varying,
  y_const character varying,
  selection_priority int
)
AS ...

在 SQL 中,使用它看起来像这样:

SELECT
  COALESCE(b.x_const, b.y_const) AS constant,
FROM a
  LEFT JOIN the_func(a.id, 'abc') AS b
  ON b.mymodel_id = a.id;

但是,我正在努力将其纳入 SQLAlchemy:

class MyModel:
    id = sa.Column(sa.Int)

    @hybrid_property
    def the_const(self):
        """Python version..."""
        # ???
    
    @the_const.expression
    def the_const(cls):
        """Use the CTE..."""
        # somehow join? 
        # ...join(
        #         aliased(
        #             func.the_func(MyModel.id, 'abc'),
        #             name="const_func"
        #         )
        #    )...
        return select([text("const_func.constant")]).as_scalar()

我认为可以将 CTE 纳入 SQLAlchemy 的 CTE(类似于 OP 在此处的做法:)但想知道是否有办法在它们存在时使用它们已经加载到数据库中(如本例所示)。

的帮助下,我找到了解决方案

class MyModel:
    id = sa.Column(sa.Int)

    @the_const.expression
    def the_const(cls):
        """Use the CTE..."""

        # Alias the CTE:
        const_func = aliased(
            func.the_func(MyModel.id, 'abc'),
            name="b"
        )

        # Set up the join:
        the_join = cls.__table__
        the_join = the_join.join(
            const_func,
            text("b.mymodel_id") == MyModel.id
        )
        # Finally select using the text() wrapper, from the joined tables
        query = select(
            [text("COALESCE(b.x_const, b.y_const)")]
        ).select_from(the_join)
        return query.as_scalar()