schema

package
v1.6.0 Latest Latest
Warning

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

Go to latest
Published: Aug 3, 2026 License: MIT Imports: 6 Imported by: 3

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrInvalidModel = fmt.Errorf("grove: invalid model type")

ErrInvalidModel is returned when a model is not a valid struct or pointer to struct.

View Source
var ErrInvalidRelation = fmt.Errorf("grove: invalid relation definition")

ErrInvalidRelation is returned when a relation definition is incomplete or incorrect. Re-exported from the root grove package for convenience within the schema package.

Functions

func ParseTag

func ParseTag(raw string) tagparser.Tag

ParseTag parses a raw tag string into structured Tag with all options.

func ToSnakeCase

func ToSnakeCase(s string) string

ToSnakeCase converts a CamelCase string to snake_case. It handles acronyms like "ID", "HTML", "URL" correctly:

"UserID"     -> "user_id"
"HTMLParser" -> "html_parser"
"APIKeyURL"  -> "api_key_url"
"SimpleTest" -> "simple_test"
"ID"         -> "id"

Types

type Field

type Field struct {
	GoName  string       // Go struct field name
	GoType  reflect.Type // Go type
	GoIndex []int        // Struct field index (for nested)
	Options FieldOptions // Parsed options
}

Field represents a single column in a table, derived from a struct field.

func NewField

func NewField(sf reflect.StructField) *Field

NewField creates a Field from a reflect.StructField. It resolves the tag (grove > bun > snake_case), parses all options, and populates the Field struct accordingly.

type FieldOptions

type FieldOptions struct {
	Column        string    // Column name in the database
	SQLType       string    // Explicit SQL type (e.g., "jsonb", "text[]")
	IsPK          bool      // Primary key
	AutoIncrement bool      // Auto-incrementing
	NotNull       bool      // NOT NULL constraint
	NullZero      bool      // Zero value treated as NULL
	Unique        bool      // UNIQUE constraint
	Default       string    // DEFAULT value
	SoftDelete    bool      // Soft delete timestamp
	ScanOnly      bool      // Read-only, excluded from INSERT/UPDATE
	Skip          bool      // Skip field entirely (tag "-")
	Privacy       string    // Privacy classification (e.g., "pii", "sensitive")
	DriverHint    string    // Driver-specific hint (e.g., "pg", "pg,mongo")
	Index         string    // Named index
	CompositeIdx  string    // Composite index group name
	CRDTType      string    // CRDT type (e.g., "lww", "counter", "set")
	TagSource     TagSource // Which tag was used
}

FieldOptions holds all parsed options for a model field.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry is a thread-safe cache of Table metadata. Tables are computed once per model type via sync.Map.

func NewRegistry

func NewRegistry() *Registry

NewRegistry creates a new empty Registry.

func (*Registry) Get

func (r *Registry) Get(model any) *Table

Get returns the Table for a registered model type. Returns nil if the model hasn't been registered.

func (*Registry) MustGet

func (r *Registry) MustGet(model any) *Table

MustGet is like Get but panics if the model is not registered.

func (*Registry) Register

func (r *Registry) Register(model any) (*Table, error)

Register registers a model and returns its Table metadata. If already registered, returns the cached Table. The model can be a pointer or value (e.g., (*User)(nil) or User{}).

type Relation

type Relation struct {
	Type       RelationType
	Field      *Field // The struct field holding the relation
	JoinTable  string // For many-to-many: join table name
	BaseColumn string // Column on the base table
	JoinColumn string // Column on the related/join table
}

Relation represents a relationship between two models.

func ParseRelation

func ParseRelation(tag string, field *Field) (*Relation, error)

ParseRelation parses relation info from a tag-derived options.

The tag format is:

grove:"rel:has-many,join:id=user_id"
grove:"rel:many-to-many,join_table:user_roles,join:id=user_id"
grove:"rel:has-one,join:id=profile_id"
grove:"rel:belongs-to,join:author_id=id"

The "rel" option specifies the relation type. The "join" option specifies the column mapping as "base_col=join_col". The "join_table" option is required for many-to-many relations.

type RelationType

type RelationType int

RelationType identifies the kind of relation.

const (
	// HasOne indicates a one-to-one relationship where the related model
	// holds the foreign key.
	HasOne RelationType = iota
	// HasMany indicates a one-to-many relationship where multiple related
	// models hold a foreign key back to this model.
	HasMany
	// BelongsTo indicates a many-to-one relationship where this model
	// holds the foreign key to the related model.
	BelongsTo
	// ManyToMany indicates a many-to-many relationship through a join table.
	ManyToMany
)

func (RelationType) String

func (rt RelationType) String() string

String returns the human-readable name of the relation type.

type Table

type Table struct {
	ModelType      reflect.Type      // The Go struct type
	Name           string            // Table name (from tag or snake_case of type name)
	Alias          string            // Table alias for queries
	Fields         []*Field          // All mapped fields (excluding skip, relations)
	FieldsByColumn map[string]*Field // column name -> field, built once
	PKFields       []*Field          // Primary key fields
	Relations      []*Relation       // Declared relations
	SoftDelete     *Field            // Soft delete field, if any
}

Table represents metadata about a model's database table.

func NewTable

func NewTable(model any) (*Table, error)

NewTable builds Table metadata from a model value (e.g., (*User)(nil)). Uses reflect to inspect the struct, reads tags, and builds the field list.

type TagSource

type TagSource int

TagSource indicates which tag was used for a field.

const (
	// TagSourceGrove indicates grove:"..." was present and used.
	TagSourceGrove TagSource = iota
	// TagSourceBun indicates bun:"..." fallback was used.
	TagSourceBun
	// TagSourceNone indicates no tag was found; field name is used as column (snake_case).
	TagSourceNone
)

func ResolveTag

func ResolveTag(field reflect.StructField) (tag string, source TagSource)

ResolveTag determines which tag to use for a struct field. Resolution order: grove > bun > snake_case of field name.

Jump to

Keyboard shortcuts

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