modelschema

package
v0.0.0-...-d283dcf Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 2, 2026 License: Apache-2.0 Imports: 8 Imported by: 0

Documentation

Overview

Package modelschema resolves the database columns of a model struct.

It is the single place where a Go struct field is mapped to a database column: the mapping is delegated to gorm's own schema parser, so column names always match what gorm actually emits, including the column tag, the ignore markers, embedded struct lifting, and gorm's commonInitialisms handling (which a plain snake case conversion does not reproduce).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FilterableIndex

func FilterableIndex(typ reflect.Type) (map[string]Column, error)

FilterableIndex returns the client-filterable columns of a model type indexed by the URL parameter name clients filter with, resolved once per type and cached. The type may be a struct or a pointer to one.

Both the parameter name and the database column name come from the parsed columns, so a filter can never name a column gorm does not emit; fields hidden from JSON stay out, because clients must not filter on them.

func GoNameIndex

func GoNameIndex(typ reflect.Type) (map[string]Column, error)

GoNameIndex returns the columns of a model type indexed by Go struct field name, resolved once per type and cached. The type may be a struct or a pointer to one.

func IsJSONType

func IsJSONType(typ reflect.Type) bool

IsJSONType reports whether a column type stores as a JSON document. The answer comes from the type itself through gorm's GormDataTypeInterface, which is how the gorm.io/datatypes types (JSON, JSONType, JSONSlice, JSONMap) and custom JSON wrappers declare their column type. Pointers are dereferenced, and the method is looked up on both receivers.

The declared name is matched by its "json" prefix rather than by equality: the datatypes family does not spell one name (JSONMap declares "jsonmap", the others "json"), and a dialect-flavored wrapper may declare "jsonb".

Consumers use it to keep text operators away from JSON columns where a dialect is strict about operand types; see the WithQuery JSON handling in the database package.

func JSONColumnSet

func JSONColumnSet(typ reflect.Type) map[string]struct{}

JSONColumnSet reports the JSON-typed columns of a model type by database name, resolved once per type and cached. The type may be a struct or a pointer to one.

Its consumers are the like-family cast in the filter renderer and the exact-match fail-closed rule in WithQuery; on a type whose columns cannot be resolved the columns render without the cast — hence nil on failure rather than an error.

func QueryColumnName

func QueryColumnName(field reflect.StructField) string

QueryColumnName resolves the URL parameter name of a struct field: the query tag wins over the json tag, which wins over the field name, and the result is converted to snake case. A "-" tag is skipped rather than used as a name, so the next source decides.

This is the client-facing name only. It never decides the database column name, which comes from gorm (see Column). Column resolution above and the urlquery decode plan are its two consumers, which is what keeps a field's bare key and its operator-filter key on one naming rule.

func TimeColumnSet

func TimeColumnSet(typ reflect.Type) map[string]struct{}

TimeColumnSet reports the time-typed columns of a model type by database name, resolved once per type and cached. The type may be a struct or a pointer to one.

Its consumer is the filter renderer normalizing time comparisons; on a type whose columns cannot be resolved it renders without normalization, which is the exact SQL every column renders on the dialects that compare time natively — hence nil on failure rather than an error.

Types

type Column

type Column struct {
	GoName     string       // Go struct field name.
	QueryName  string       // URL parameter name: query tag, else json tag, else field name, in snake case.
	DBName     string       // Database column name resolved by gorm.
	Type       reflect.Type // Go type of the underlying struct field.
	Index      []int        // Struct field index path, usable with reflect.Value.FieldByIndex.
	Filterable bool         // Whether clients may filter on the column through the URL.
}

Column is one database column of a model.

QueryName and DBName are deliberately separate: QueryName is the URL parameter clients filter by and stays a front-end contract, while DBName is whatever gorm writes into SQL. They are usually equal, and diverge when a model carries a column tag or a field name gorm renders differently.

func Columns

func Columns(typ reflect.Type) ([]Column, error)

Columns returns every database column of a model struct type, sorted by database column name so repeated calls and generated code stay stable. The type may be a struct or a pointer to one.

type ColumnClass

type ColumnClass int

ColumnClass is the aggregate capability a column type carries. It decides which reference gg gen writes for the column and which aggregate functions the string-name constructors accept for it, so both consumers read the same rule rather than each carrying a copy that could drift.

const (
	// ColumnClassOther carries the aggregate functions that cannot be silently
	// wrong on any type: COUNT, COUNT DISTINCT, MIN and MAX.
	ColumnClassOther ColumnClass = iota
	// ColumnClassNumeric additionally carries SUM and AVG.
	ColumnClassNumeric
	// ColumnClassTime additionally carries time bucketing.
	ColumnClassTime
)

func ClassifyColumn

func ClassifyColumn(typ reflect.Type) ColumnClass

ClassifyColumn reports the aggregate capability of a column type. Pointers are dereferenced, since an aggregate reads the pointed-to value.

Classification reads reflect.Kind only. Recognizing decimal types through driver.Valuer looks tempting, but uuid, JSON and enum types stored as text implement it too, and treating those as numeric would reintroduce exactly the failure the split exists to prevent: MySQL and SQLite answer SUM over a text column with 0 and a warning rather than an error, so the mistake reaches a report as a plausible wrong number instead of a failure. A decimal stored as a struct is therefore classified as other, and is summed through SumOf, whose column is checked against the model schema at build time.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL