Documentation
¶
Overview ¶
Package stdenttypeid is the Go-side companion to a Postgres `typeid` composite type. It carries a typeid value as its canonical *printable* form (e.g. `upld_01j8...`) on the Go side while letting ent / pgx round-trip it transparently against a `public.typeid` column.
Why this exists: the Postgres `typeid` is a composite type of the shape `(prefix text, uuid uuid)`. pgx encodes a Go string parameter as an anonymous record, which Postgres rejects with `input of anonymous composite types is not implemented (SQLSTATE 0A000)` for every `WHERE id = $1` / `DELETE WHERE id = $1` query. Reads surface as the raw composite literal `(upld,019e...)` rather than the printable typeid form a wire API wants.
ID solves both halves at the ent column-type layer:
ID.Scan normalises whatever Postgres returns (either the composite literal `(prefix,uuid)` or an already-printable `prefix_base32suffix`) into the printable form. The Go-side value of a typeid column is therefore always the same shape a wire API consumes.
ID.FormatParam makes ent's SQL builder render the parameter placeholder as `public.typeid_parse($N)` so Postgres receives a real `typeid` expression, not an anonymous composite. Every ent predicate that takes a typeid value (IDEQ, IDGT, IDIn, DeleteOneID, …) inherits the wrap for free.
ID.Value passes the printable string through to `typeid_parse()` unchanged.
The base32 alphabet mirrors the Crockford-style alphabet (`0123456789abcdefghjkmnpqrstvwxyz`) that the companion SQL `typeid_print()` / `base32_encode()` functions use EXACTLY so the Go-side normalisation produces the same string `typeid_print()` does for the same composite — round-trip tests against a known vector pin this end-to-end.
The matching Postgres-side schema (the `typeid` composite, the `typeid_parse()` / `typeid_print()` / `typeid_generate()` functions, and the Crockford `base32_encode()` helper) is the caller's responsibility; this package is the Go-side adapter only.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type ID ¶
type ID string //nolint:recvcheck // sql.Scanner needs pointer; ent calls Value/FormatParam on value.
ID is the Go-side companion to a Postgres `typeid` composite. The zero value is the empty string; non-empty values are always in printable form (`prefix_base32suffix`).
Use ID via ent's `field.String("...").GoType(stdenttypeid.ID(""))` declaration; ent will hand out and accept ID values everywhere the column appears (predicates, builders, mutations, edges that reuse the column via `.Field("...")`).
Receiver mix is deliberate: ID.Value, ID.String and ID.FormatParam are value receivers because ent passes the ID by value into its SQL builder (where the interface assertions live), and ID.Scan is a pointer receiver because the database/sql.Scanner contract requires it. This is the same pattern github.com/google/uuid uses; the recvcheck linter is silenced at the type declaration only.
func (ID) FormatParam ¶
FormatParam implements ent's entsql.ParamFormatter interface, which ent's SQL builder calls for every parameter that is bound from this Go type. Wrapping the placeholder with `public.typeid_parse(...)` makes Postgres convert the bound text into a real `typeid` composite before evaluating the predicate. The `public` schema is named explicitly so the rewrite is not search_path-dependent (per-tenant roles often have search_path pinned away from public; the function is expected to live in public).
func (*ID) Scan ¶
Scan implements database/sql.Scanner. Accepts both the raw composite literal Postgres emits for a `typeid` column (`(prefix,uuid)`) and the already-printable form (`prefix_base32`) — the latter so callers that select `typeid_print(id)` directly continue to work unchanged.
func (ID) Value ¶
Value implements database/sql/driver.Valuer. The driver sees the printable string; ID.FormatParam ensures Postgres receives it via `public.typeid_parse($N)`.