Description
Describe the bug
Types for scalar domain types return type Opaque and for array domain types they just fail.
To Reproduce
Given the following schema:
create domain pos_int as int check (value > 0);
create domain non_empty_array as int[] check (array_length(value, 1) > 0);
create domain pos_array as pos_int[];
create table domain_test(
id serial primary key,
int_field int,
array_field int[],
pos_int pos_int,
non_empty_array non_empty_array,
pos_array pos_array
);
insert into domain_test(int_field, array_field, pos_int, non_empty_array, pos_array)
values (1, '{1,2,3}', 1, '{1,2,3}', '{1,2,3}');
Querying for the types on domain_test
returns the following:
select graphql.resolve($$
query {
__type(name: "domain_test") {
fields {
name
type {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
$$);
{
"data": {
"__type": {
"fields": [
{
"name": "nodeId",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
}
},
{
"name": "id",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
},
{
"name": "int_field",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "array_field",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
},
{
"name": "pos_int",
"type": {
"kind": "SCALAR",
"name": "Opaque",
"ofType": null
}
}
]
}
}
}
Querying the data will work for the fields on the Opaque types:
select graphql.resolve($$
query {
domain_testCollection{
edges {
node {
id
int_field
array_field
pos_int
}
}
}
}
$$);
{
"data": {
"domain_testCollection": {
"edges": [
{
"node": {
"id": 1,
"pos_int": 1,
"int_field": 1,
"array_field": [
1,
2,
3
]
}
}
]
}
}
}
And fails for fields with an array domain_type:
select graphql.resolve($$
query {
domain_testCollection{
edges {
node {
id
non_empty_array
}
}
}
}
$$);
{
"data": null,
"errors": [
{
"message": "Unknown field 'non_empty_array' on type 'domain_test'"
}
]
}
You can attempt the above with pos_array
and get a similar result.
Expected behavior
For fields with domain types to resolve to there domain type or at least the domain base type.
E.g.
select graphql.resolve($$
query {
__type(name: "domain_test") {
fields {
name
type {
name
kind
ofType {
name
kind
ofType {
name
kind
}
}
}
}
}
}
$$);
Would return:
{
"data": {
"__type": {
"fields": [
{
"name": "nodeId",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "ID",
"ofType": null
}
}
},
{
"name": "id",
"type": {
"kind": "NON_NULL",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
},
{
"name": "int_field",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "array_field",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
},
{
"name": "pos_int",
"type": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
},
{
"name": "non_empty_array",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
},
{
"name": "pos_array",
"type": {
"kind": "LIST",
"name": null,
"ofType": {
"kind": "SCALAR",
"name": "Int",
"ofType": null
}
}
}
]
}
}
}
The behavior of the field itself on querying would be the same as it's base type.
Screenshots
N/A
Versions:
- PostgreSQL: 15
- pg_graphql commit ref: ec3f7d5
Additional context
I think I have a possible fix for this and I'l like to try opening a pr to fix this.
A simple solution would be to resolve the base type of the domain object itself.
To my understanding domain types always have to eventually resolve to a built in sql scalar or array type so this seems like a valid solution.
While this would technically be a breaking change Opaque isn't particularly useful so it could also hide behind a schema directive flag but that would be opt out. This is also a possible fix for #370.
Let me know if you agree and I'll submit a pr.
The complete fix would be to generate new types for domain types.
That is breaking change and some client might not care to know about anything but the base type. It'll have to be behind a schema directive flag that's opt in.
I won't be attempting this approach right away just spitballing a final solution.