Smart tag to shortcut accessing an attribute from a related table
- Dominant language
- TypeScript
- Stars
- 12.9k
- Forks
- 625
- Avg merge
- 5h 23m
- Merged PRs (30d)
- 24
Description
Feature request via Discord, essentially `@ref` but for attributes rather than whole tables.
From https://discord.com/channels/489127045289476126/1232250825125134400/1232250825125134400:
## Discord question
I have a table, let's call it person (id, name) and a view, let's call it person_address (person_id, address_calculated_in_view). Both of them are related via a foreign key (i.e. id on person <> person_id on person_address), but note that this is NOT a materialized view, so there's no indexes on person_address.
Now with the @ref smart tag, I believe I would be able to "join" those so that in graphql I would get
```graphql
person {
personAddress {
addressCalculatedInView
}
}
```
And that is great - however, what I would actually need, is a way to get
```graphql
person {
addressCalculatedInView
}
```
Right now, what I do for this, is define a function
```sql
person_address_calculated_in_view(p person)
SELECT address_calculated_in_view FROM person_address WHERE person_address.person_id = p.id
```
Unfortunately though, this is *significantly* more expensive to run than a simple join. While for my data the function takes ~5ms to execute, it'll take 5ms PER row in person, which becomes very slow very fast.
Ideally, I would like to be able to specify a @ref to a single field, such that graphile can just join the view to the base table.
Is there curerntly a way to do this for me? If not, what would be the best way forward to get this - can the @ref tag somehow be extended via plugins maybe?
Thanks in advance for any pointers!
#### Benjie's Discord response
Interesting idea. `@ref` would not be the right smart tag for this, we'd need a new one (e.g. `@refColumn`) but it's definitely feasible. You should file an issue about it. In the mean time, I would personally solve this via a `makeExtendSchemaPlugin`, something like:
```ts
export const MyPlugin = makeExtendSchemaPlugin(build => {
return {
typeDefs: gql`extend type Person { addressCalculatedInView: String }`,
plans: {
Person: {
addressCalculatedInView($person) {
const $view = $pgSelectSingle.sinleRelation('relationNameHere');
// OR: const $view = build.input.pgRegistry.pgResources.person_address.get({ person_id: $person.get('id') });
return $view.get('address_calculated_in_view');
}
}
}
}
});
```
Contributor guide
Assessment
This issue has not been assessed yet.