SIGN IN SIGN UP

Add backlinks to query builder (#961)

Object models now have a `__backlinks__` field, which is set to a `GelObjectBacklinksModel`. This backlinks model contains multi links to `std::BaseObject`.

These new backlinks models are generated during reflection. At runtime, intersections generate a backlink model alongside the intersection type.

A simple query with backlinks:
```py
default.Inh_A.__backlinks__.l
.is_(default.Link_Inh_A)
.select(n=True, l=True)
```

```edgeql
WITH baseobject_and_link_inh_a := (
    default::Inh_A.<l [is default::Link_Inh_A]
)
SELECT baseobject_and_link_inh_a {
    n,
    l := baseobject_and_link_inh_a.l { * },
}
```

A more complex query with backlinks:
```py
default.Link_Inh_AB.l  # Link
.is_(default.Inh_AC)  # Intersection
.__backlinks__.l.is_(default.Link_Inh_A)  #  Backlink
.select(n=True, l=True)
```

```edgeql
WITH baseobject_and_link_inh_a := (
    (
        default::Link_Inh_AB.l [is default::Inh_AC]
    ).<l [is default::Link_Inh_A]
)
SELECT baseobject_and_link_inh_a {
    n,
    l := baseobject_and_link_inh_a.l { * },
}
```

Also works inside shapes:
```py
default.Inh_AB.select(
    a=lambda x: x.__backlinks__.l.is_(default.Link_Inh_AB).limit(1).n
)
```

```edgeql
WITH inh_ab := default::Inh_AB
SELECT inh_ab {
    a := (
        SELECT (inh_ab.<l [is default::Link_Inh_AB]) { * }
        LIMIT 1
    ).n,
}
```
D
dnwpark committed
8a956d62b380db36ecaacc57952a94b1bab40d6a
Parent: e0a14b6
Committed by GitHub <noreply@github.com> on 11/4/2025, 11:25:35 PM