graphile / graphile/crystal

Foreign Key Smart Tags on Types

Open
#2,346 12 comments 0 reactions 0 assignees View on GitHub
😓 cannot-reproduce
Dominant language
TypeScript
Stars
12.9k
Forks
625
Avg merge
5h 23m
Merged PRs (30d)
24

Description

### Summary

I have a function that returns a `indexed_foo` type, which comes from a `foo` table. `indexed_foo` results are just a `SETOF foo` with an extra `index` column (JOIN-ed from another table), so a `SELECT * FROM indexed_foo(5)` returns:

```
id | foo_field_1 | foo_field_2 | ...other foo fields | index
5 | 'abc' | 123 | ...other foo fields | 0
```

My function sort of works, but in the API the returned `indexed_foo` results only have the `foo` columns (eg. `foo.baz_id`), not their relations (eg. not `foo.baz.qux`). This makes sense, because while `foo` has those relations, `indexed_foo` doesn't.

The `@foreignKey` documentation mentions that types are supported, but ...

> Composite types (one direction only)

I wasn't clear what that meant exactly: isn't `@foreignKey` _always_ one direction, from the thing being tagged, to its foreign table?

So, I experimented, and added a `@foreignKey` to connect my `indexed_foo` type to `foo`:

COMMENT ON TYPE public.indexed_foo IS E'@foreignKey (id) references foo(id);

Since each `indexed_foo` has one `foo_id`, I expected an API structure of:

indexed_foo(id:5) {
foo {
...foo fields

However, I instead got:

indexed_foo(id: 5) {
fooById {
...array of objects with foo fields

That works (my client can extract the single record from the array), but it confused me. Each `indexed_foo` only has one `id`, so shouldn't that be a one-to-one relationship in the API, not a one-to-many?

Two (hopefully quick) questions:

1. Why does a `COMMENT ON TYPE public.indexed_foo IS E'@foreignKey (id) references foo(id);` result in `indexed_foo` getting an array child `fooById` (ie. one-to-many) when each `indexed_foo` only has one ID?
2. Is there any way to convert my array endpoint `fooById` into a single-child endpoint `foo`?

### Additional context

Not that it matters, but `foo` is actually the `recommendation_groups` table I mentioned in a previous question. I've reduced it to `foo` here to keep the irrelevant details as abstract as possible, and focus on the API/relationship question.

OS: Linux (relatively recent version)
Node: Latest (or like a minor version behind)
PostgreSQL: 14.15
Postgraphile: 4.12.11 (I swear I'm going to upgrade to 5 soon ...)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.