]> git.ipfire.org Git - thirdparty/sqlalchemy/sqlalchemy.git/commitdiff
Add ORM documentation for as_comparison()
authorMike Bayer <mike_mp@zzzcomputing.com>
Thu, 25 Apr 2019 15:46:31 +0000 (10:46 -0500)
committerMike Bayer <mike_mp@zzzcomputing.com>
Thu, 25 Apr 2019 15:51:30 +0000 (10:51 -0500)
In #3831 we added the ability for SQL functions to be used in
primaryjoin conditions as the source of comparison, however we
didn't add documentation from the main relationship docs so
nobody could find it unless they read the migration notes.
Since the two use cases that have come up for this are
materialized path with string functions, and geometry functions,
add the example based on the use case requested in
https://github.com/geoalchemy/geoalchemy2/issues/220#issuecomment-486709055

This example hasn't been tested yet and is subject to
revision.

Change-Id: I410d8ffade3f17cf616fc5056f27d7d32092207b

doc/build/orm/join_conditions.rst

index e9c51c14d87a86861c160172cdd9d186a08afebe..8a29fdc5d73a3bfdea2b1225e9633dec01c8e518 100644 (file)
@@ -294,6 +294,45 @@ Will render as::
    flag to assist in the creation of :func:`.relationship` constructs using
    custom operators.
 
+Custom operators based on SQL functions
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A variant to the use case for :paramref:`~.Operators.op.is_comparison` is
+when we aren't using an operator, but a SQL function.   The typical example
+of this use case is the PostgreSQL PostGIS functions however any SQL
+function on any database that resolves to a binary condition may apply.
+To suit this use case, the :meth:`.FunctionElement.as_comparison` method
+can modify any SQL function, such as those invoked from the :data:`.func`
+namespace, to indicate to the ORM that the function produces a comparison of
+two expressions.  The below example illustrates this with the
+`Geoalchemy2 <https://geoalchemy-2.readthedocs.io/>` library::
+
+    from geoalchemy2 import Geometry
+    from sqlalchemy import Column, Integer, func
+    from sqlalchemy.orm import relationship, foreign
+
+    class Polygon(Base):
+        __tablename__ = "polygon"
+        id = Column(Integer, primary_key=True)
+        geom = Column(Geometry("POLYGON", srid=4326))
+        points = relationship(
+            "Point",
+            primaryjoin="func.ST_Contains(foreign(Polygon.geom), Point.geom).as_comparison(1, 2)",
+            viewonly=True,
+        )
+
+    class Point(Base):
+        __tablename__ = "point"
+        id = Column(Integer, primary_key=True)
+        geom = Column(Geometry("POINT", srid=4326))
+
+Above, the :meth:`.FunctionElement.as_comparison` indicates that the
+``func.ST_Contains()`` SQL function is comparing the ``Polygon.geom`` and
+``Point.geom`` expressions. The :func:`.foreign` annotation additionally notes
+which column takes on the "foreign key" role in this particular relationship.
+
+.. versionadded:: 1.3 Added :meth:`.FunctionElement.as_comparison`.
+
 .. _relationship_overlapping_foreignkeys:
 
 Overlapping Foreign Keys