Skip to content

filter is exposed on a query-tagged VOLATILE function connection, then crashes Grafast at runtime #231

Description

@dilame

Repro

https://github.com/dilame/ouchmyfinger/tree/computed-function-connection-filter

Versions

  • postgraphile@5.0.0-rc.10
  • graphile@5.0.0-rc.6
  • postgraphile-plugin-connection-filter@3.0.0-rc.3
  • @graphile/simplify-inflection@8.0.0-rc.5

Expected

I may be creating a contradictory schema contract here by exposing a VOLATILE function as a query field.

Still, I would expect one of these outcomes:

  • filter works on the function-backed connection, or
  • unsupported filter args should not be exposed for that field, or
  • schema generation/startup fails clearly, or
  • the request fails with a clear validation/planning error.

Actual

A SQL set-returning function is exposed as a query field via smart tags:

create function app_api.asset__my_wallet()
  returns setof asset.wallet
  language sql
  security definer
as $$
  select ...
$$;

Important detail: the function is not marked STABLE, so PostgreSQL treats it as VOLATILE.

The unfiltered query works:

query {
  appApiAssetMyWallet {
    nodes {
      balance
      segment { code }
    }
  }
}

But both scalar and relation filters fail at runtime:

query {
  appApiAssetMyWallet(filter: { segmentId: { equalTo: 1 } }) {
    nodes { balance }
  }
}
query {
  appApiAssetMyWallet(
    filter: { segment: { code: { equalTo: "main" } } }
  ) {
    nodes { balance }
  }
}

Server log:

PgSelect<app_api_asset__my_wallet(mutation)>[...] may not depend on ApplyInput[...] as it would create an invalid heirarchy (for example a cycle or an unreachable path through the graph).

at StepTracker.addStepDependency (.../grafast/dist/engine/StepTracker.js:297:19)
at StepTracker.addStepUnaryDependency (.../grafast/dist/engine/StepTracker.js:345:21)
at PgSelectStep.addUnaryDependency (.../grafast/dist/step.js:415:47)
at PgSelectStep.apply (.../@dataplan/pg/dist/steps/pgSelect.js:465:40)
at .../postgraphile-plugin-connection-filter/dist/PgConnectionArgFilterPlugin.js:327:46
at processAfter (.../grafast/dist/operationPlan-input.js:204:28)
at Object.autoApply (.../grafast/dist/operationPlan-input.js:106:17)

The interesting part is that the log says:

PgSelect<app_api_asset__my_wallet(mutation)>

So the function is exposed as a query field, but internally still behaves as a mutation-like resource because it is VOLATILE.

Why this matters

The generated schema exposes a filter argument, and the unfiltered field works, so this looks safe from the client side.

In production, adding filter turns the field into a masked internal GraphQL error. That makes the issue hard to diagnose because the public response only contains a generic masked error id.

If this is unsupported/invalid configuration, it would be much easier to debug if the schema did not expose filter here, or if startup/request planning failed with a clearer error.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions