When multiple functions share the same name but have different parameter types (valid PostgreSQL overloading), PgProceduresPlugin silently drops all overloads, not just duplicates.
Example
CREATE SCHEMA computed;
CREATE FUNCTION computed.code(sales.orders) RETURNS text AS $$ ... $$ LANGUAGE sql STABLE;
CREATE FUNCTION computed.code(work.jobs) RETURNS text AS $$ ... $$ LANGUAGE sql STABLE;
CREATE FUNCTION computed.code(partner.accounts) RETURNS text AS $$ ... $$ LANGUAGE plpgsql STABLE;
These are three distinct PostgreSQL functions (different OIDs, different parameter types). Each takes a different table's row type as its first argument, making them valid computed column candidates for three different GraphQL types (SalesOrder, WorkJob, PartnerAccount).
Expected: All three appear as code fields on their respective GraphQL types.
Actual: None of them appear. All are silently dropped.
Cause
In PgProceduresPlugin, the overload check compares only pronamespace and proname, ignoring proargtypes:
const overload = introspection.procs.find((p) =>
p.pronamespace === pgProc.pronamespace &&
p.proname === pgProc.proname &&
p._id !== pgProc._id
);
if (overload) {
return; // skips this function entirely
}
Since each function finds one of the others as an "overload", all overloads are dropped.
Why this matters
This pattern is natural for computed columns: a function named is_open that works on sales.orders, sales.orderlines, and inbound.deliverylines is three logically separate computed columns. Each targets a different type and there's no naming conflict in the GraphQL schema.
Possible fix
When the first parameter is a composite (row) type for different tables, these aren't true overloads from a GraphQL perspective, they produce fields on different types. The check could be relaxed to allow functions with the same name when their first parameter refers to a different table, or the resource name could include the table name to disambiguate (e.g., orders_code, jobs_code).
Workaround
Rename each function to include the table name prefix: computed.orders_code(sales.orders), computed.jobs_code(work.jobs), etc. However, this is a lot less nice for SQL-usage of the database. What was previously:
SELECT orders.code FROM sales.orders
-- or
SELECT computed.code(order.*) FROM sales.orders
Must now become:
SELECT computed.orders_code(order.*) AS code FROM sales.orders
Versions
- postgraphile 5.0.0-rc.9
- graphile-build-pg 5.0.0-rc.7
When multiple functions share the same name but have different parameter types (valid PostgreSQL overloading), PgProceduresPlugin silently drops all overloads, not just duplicates.
Example
These are three distinct PostgreSQL functions (different OIDs, different parameter types). Each takes a different table's row type as its first argument, making them valid computed column candidates for three different GraphQL types (SalesOrder, WorkJob, PartnerAccount).
Expected: All three appear as code fields on their respective GraphQL types.
Actual: None of them appear. All are silently dropped.
Cause
In PgProceduresPlugin, the overload check compares only pronamespace and proname, ignoring proargtypes:
Since each function finds one of the others as an "overload", all overloads are dropped.
Why this matters
This pattern is natural for computed columns: a function named
is_openthat works onsales.orders,sales.orderlines, andinbound.deliverylinesis three logically separate computed columns. Each targets a different type and there's no naming conflict in the GraphQL schema.Possible fix
When the first parameter is a composite (row) type for different tables, these aren't true overloads from a GraphQL perspective, they produce fields on different types. The check could be relaxed to allow functions with the same name when their first parameter refers to a different table, or the resource name could include the table name to disambiguate (e.g., orders_code, jobs_code).
Workaround
Rename each function to include the table name prefix:
computed.orders_code(sales.orders),computed.jobs_code(work.jobs), etc. However, this is a lot less nice for SQL-usage of the database. What was previously:Must now become:
Versions