Skip to content

Add generated column exclusion options#53

Draft
ragokan wants to merge 2 commits into
sqlc-contrib:mainfrom
ragokan:codex/insert-column-exclusions
Draft

Add generated column exclusion options#53
ragokan wants to merge 2 commits into
sqlc-contrib:mainfrom
ragokan:codex/insert-column-exclusions

Conversation

@ragokan

@ragokan ragokan commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add insert_columns.exclude to omit database-managed fields from generated insert queries.
  • Add update_columns.exclude to omit fields from generated update SET clauses while keeping them available for filters or selected output.
  • Cast update_mask args to text[] so sqlc generates typed []string params instead of interface{}.

Validation

  • go test ./...

@ragokan ragokan changed the title Add insert column exclusion option Add generated column exclusion options Jun 10, 2026
@iamralch

Copy link
Copy Markdown
Contributor

Thanks for putting this together, @ragokan — column exclusion for the generated INSERT/UPDATE queries is a genuinely useful addition. 👍

Heads up that I can see this is still WIP and you haven't formally asked for review, so please treat this as early design input, not a review — no rush to act on any of it.

The one thing I'd love your thoughts on before it solidifies is the config shape. Right now it's two flat exclude lists (insert_columns / update_columns). I've been wondering whether the rule is better expressed as a property of the column rather than two parallel operation lists — something like:

options:
  models:
    - name: "*"               # applies to every table
      columns:
        created_at: immutable # in INSERT, out of UPDATE
    - name: user
      columns:
        id: read_only         # out of INSERT and UPDATE
trait INSERT UPDATE SET
(none)
immutable
read_only

Why I lean this way:

  • "id is never inserted" is really a fact about the column, so the rule lives on the column — and one trait replaces having to keep two exclude lists in sync.
  • Reads like ORM field annotations (Ent/Prisma), so it should feel familiar.
  • A "*" catch-all keeps the common "timestamps on every table" case down to one block.

Two smaller notes:

  • The update_mask::text[] cast is a nice catch, independent of all the above — definitely keep it.
  • Good call leaving SELECT * / RETURNING * alone; listing explicit columns there makes sqlc emit a separate per-query row struct instead of reusing the model type, so we want to stay off the read side.

All very open to pushback — happy to talk it through whenever you pick this back up.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants