Skip to content

v0.3.0 — name an index

Choose a tag to compare

@tanmaymishu tanmaymishu released this 17 Oct 12:53
· 8 commits to main since this release

Index and UniqueKey can take a name

v0.2.0 gave a multi-column index a table prefix, so two tables wanting (user_id, position) stopped colliding on a name that is schema-global in Postgres. That fixed new tables and did nothing for the ones that already exist.

An index in a migration that has already run has a name in somebody's database. users_published_idx is not what this builder derives, and there was no way to ask for it — so the whole statement had to be hand-written. An audit of the first application built on this module put ~41% of its raw SQL down to exactly that: 82 CREATE INDEX lines whose columns the DSL expressed perfectly and whose names it could not.

t.Index("profile_published", "id").Name("users_published_idx")
t.UniqueKey("email").Name("users_email_unique_idx")

Both methods now return a *NamedConstraint. Every existing call site compiles untouched — a Go caller may ignore a return value — and t.Index("user_id") still reads as a statement.

The defaults do not move

Three of the five new tests pin existing behaviour rather than the feature:

  • an unnamed index is still derived as <table>_<cols>_index
  • an empty name is ignored, not accepted
  • an unnamed unique key on Postgres stays anonymous

That last one is the load-bearing case. A named unique now emits CONSTRAINT <name> UNIQUE (...) on every dialect, because the name is what Postgres reports when a row is refused and that is the reason to want control of it. Promoting every unique key to a named constraint would change the output of every migration already written, so without a name nothing changes.

Verification

Against real Postgres, not against the generated string: a two-surface attachment schema where both tables declare (comment_id, position) migrates up, down and back up carrying the names asked for. The two feature tests fail against a no-op Name, which is the only way to know they test anything.

Full suite green standalone (GOWORK=off), with MIGRATION_POSTGRES_DSN set so the 21 Postgres tests actually run rather than skipping, and under -race.