Skip to content

Functions with same name but different parameter types are silently dropped (overload detection too aggressive) #2972

@GeertJohan

Description

@GeertJohan

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions