rowtype-yoga / rowtype-yoga/purescript-yoga-postgres

Expose the set of columns a query references (for dead-column analysis)

Open
#2 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
PureScript
Stars
1
Forks
1
PR merge metrics
No merged PRs in 30d

Description

What I'm after

A way to recover, from a finished Q, the set of columns the query references across all clauses — so a consumer can compute dead = schema.columns ∖ reached (dead-column / unused-column analysis).

I'm building this on top of yoga-postgres in notothenia (schema cartography). The dual already works for free: drop a column from the schema type and any query that reached it fails to compile at its call site, straight out of ResolveColumn. This issue is about the other direction — "which columns does no query touch?"

The gap

A finished Q tables result params stage = Q { sql, values } doesn't retain the reference set (line refs against 35e8250):

  • The clause symbols (select @"…", where_ @"…") are reflected into the runtime sql string and discarded at the type level.
  • result (ParseSelect) is keyed by output alias — projection reach only, and lossy under AS.
  • params (ParseWhere) is keyed by param name ($x) typed to the compared column — the column identity is gone.

So the referenced-column set isn't recoverable from the public type, even though the parser plainly computes it while resolving.

The keystone

Every column reference in every clause funnels through a single class — ResolveColumn word tables typ (Schema.purs:689) — after the keyword/function/param/literal exclusions have fired (SELECT via ParseSelectGo/ParseSelectHandleAS; WHERE via the FlushWhereWord* chain, first ResolveColumn at :1639; ORDER/GROUP/HAVING likewise). Anything hung at that point inherits the classification for free and stays correct as the parser grows.

Two designs (full writeup + line citations + edge cases)

📄 https://github.com/afcondon/notothenia/blob/main/docs/rung3-reach-ask-yoga.md

In short:

  • Option A (my recommendation) — add a reached :: Row Type parameter to Q, fed at the ResolveColumn chokepoint, canonically keyed "<table>.<column>". Correct-by-construction (reuses your own exclusions); cost is a kind change to Q (put reached last so inferred call sites are unaffected and only explicit Q annotations gain a param) and threading an accumulator through the Parse*Go / FlushWhereWord chains.
  • Option B — retain the clause symbols on Q and add a standalone ReferencedColumns clauses tables :: Row Type collector that re-walks them reusing the existing SkipSpaces/ExtractWord/SplitOnDot/ResolveColumn primitives. Smaller blast radius on the parser chains, but it has to re-derive token classification, which risks drifting from the real parser (aggregates, AS, functions).

Edge cases I'd want your call on: SELECT * / selectAll, aggregate args (count(id)), AS aliases (record the underlying column, not the alias), JOIN ON columns, and "<table>.<column>" as the canonical key.

Offer

Happy to write the PR for whichever option you prefer — you own the parser and know its delicate spots, so I'd rather get your read on the approach first. Also genuinely open to "this belongs in your layer, not yoga's" if that's your call.

(Discussions are off on this repo, so I filed it as an issue — feel free to convert if you turn them on.)

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Read docs/rung3-reach-ask-yoga.md first, then inspect Schema.purs at ResolveColumn and the ParseSelectGo, ParseSelectHandleAS, and FlushWhereWord chains. Get a maintainer decision between the two designs and the listed edge cases before starting. Done means the chosen approach exposes the referenced-column set while preserving the parser's existing classification behavior.

Written by the indexing model from the issue text.

Assessment

Tech stack
sql
Domain
databases
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.