Skip to main content
Copper models are plain Go structs. There is no ORM and no base class to extend; a model is simply a struct whose fields are tagged with the columns they map to.

Defining a Model

Models conventionally live in your package’s models.go. Columns are mapped to fields using db: tags, and you may add json: tags alongside them when the same struct shapes your API responses or Inertia props:
pkg/rockets/models.go
The db: tags are used both when scanning rows in Queries and when generating SQL fragments with Query Builder.

Nullable Columns

Pointer fields map to nullable columns. A NULL value scans as nil, and writing nil stores a NULL. If you would like to build pointers inline, the cvars.Ptr helper saves you a temporary variable:

The readonly Modifier

The ,readonly modifier marks columns that are written once and never updated, such as id and created_at. Readonly columns are included when inserting but excluded when updating, which is enforced by the Query Builder SetColumns and SetValues functions.

Tag Rules

  • Fields without a db: tag, tagged db:"-", or unexported are skipped.
  • Embedded structs are flattened; their tagged fields are included recursively.
  • db:"col,readonly" includes the column in inserts but excludes it from updates, as described above.

Custom Column Types

Since scanning is built on database/sql, any type that implements driver.Valuer and sql.Scanner may be used as a column type. This lets a domain type validate and format itself while being stored as a simple column:

Next

Now that you have a model, you may want to read and write it with Queries, or generate the SQL fragments from its tags with Query Builder.