Skip to content

Snowflake: @remove/@add directive that empties SELECT list fails with Parser Error #573

@amitdeshmukh

Description

@amitdeshmukh

Description

When a role-based @remove(ifRole:) or @skip directive strips the only user-selected field from a sub-select, GraphJin emits an empty column list and the Snowflake emulator rejects the query with:

001007 (-1): query execution failed: query execution error: Parser Error: SELECT clause without selection list

Reproduction

Any query where a directive removes the only field under a sub-select trips this. The existing integration test tests/Example_queryWithAddAndRemoveDirective2 is the canonical repro:

query {
  products(limit: 2, order_by: { id: asc }) {
    id
    name @add(ifRole: \"user\")
  }
  users(limit: 3, order_by: { id: asc }) {
    id @remove(ifRole: \"anon\")
  }
}

When run as the anon role, id @remove(ifRole: \"anon\") drops id from the users sub-select, leaving nothing between SELECT and FROM.

cd tests && go test -v -db snowflake -run '^Example_queryWithAddAndRemoveDirective2$'

Expected: {\"products\":[{\"id\":1},{\"id\":2}],\"users\":[{},{},{}]}
Actual: Snowflake parser rejects the SQL.

Scope

  • Other dialects (Postgres, MySQL, MariaDB, SQLite, MSSQL, Oracle, MongoDB) handle this correctly — postgres emits something like `SELECT json_agg(json_build_object()) ... FROM users` which is a valid empty JSON object per row.
  • Snowflake's inner rendering apparently produces a bare `SELECT FROM users` instead of `SELECT NULL FROM users` or equivalent.
  • Reproduces against the ghcr.io snowflake-emulator currently pinned in `tests/dbint_test.go`. Haven't verified against real Snowflake — worth checking whether production Snowflake is more forgiving.

Suggested fix

In the Snowflake dialect's inner-child / JSON-field renderer, when every user field has been filtered out (`SkipRender == SkipTypeDrop` / `SkipTypeBlocked` / `SkipTypeNulled` on all fields), emit a placeholder column so the SELECT is non-empty. The postgres / mssql dialects already have a `RequiresNullOnEmptySelect()` style hook in their inline-child path — mirroring that for Snowflake should cover it.

Not a regression

This reproduces on `master` before any recent PRs — not introduced by the expression-aggregate work (#572) or earlier. Filing separately so it can be triaged on its own scope.

Environment

  • GraphJin: master
  • Snowflake emulator: `ghcr.io/nnnkkk7/snowflake-emulator` (SHA pinned in `tests/dbint_test.go`)
  • Go: 1.25.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions