orm

package
v0.1.10 Latest Latest
Warning

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

Go to latest
Published: Nov 12, 2020 License: MIT Imports: 21 Imported by: 0

Documentation

Overview

Package orm transfers a struct into an ORM by simple embedding the orm.Model.

A model requires one or more primary keys which can be set by tag. If tag is set, the field ID will be defined as primary key. An error will return if no key is set.

Configuration If the model has the function Default(TableName, DatabaseName, SchemaName, Builder, Logger, Cache) some default values can be set. By default, the TableName is the plural of the struct name. Database and SchemaName are taken from the builder configuration.

Tags custom: if set, the field is declared as custom field. This means the field is not required in the database table. primary: set a field as primary field. if none is set, it checks if the field ID exists and sets this as default primary. column: set a table column name. by default the column name is snake style of the field name. permission: rw can be set for read and write. if none is required just type permission. The read and write privileges will be set to false. select: if a custom sql statement is required. relation: hasOne, belongsTo, hasMany, m2m fk,afk join_table, join_fk, join_akf polymorphic: polymorphic_value:

restrictions: self reference is only allowed on m2m polymorphic is only allowed on hasOne, hasMany embedded fields must be Exported structs and no orm2.Model in it is allowed. (TODO fix this, maybe useful?)

Index

Constants

View Source
const (
	CREATE = "create"
	UPDATE = "update"
	DELETE = "delete"
	FIRST  = "first"
	ALL    = "all"
	COUNT  = "count"
)
View Source
const (
	CreatedAt = "CreatedAt"
	UpdatedAt = "UpdatedAt"
	DeletedAt = "DeletedAt"
)
View Source
const (
	HasOne     = "hasOne"
	BelongsTo  = "belongsTo"
	HasMany    = "hasMany"
	ManyToMany = "m2m"
)

available relations.

View Source
const (
	BLACKLIST = 0
	WHITELIST = 1
)

white/blacklist policy

View Source
const (
	TagValidate = "validate"
)

Variables

View Source
var (
	ErrUpdateNoChanges = errors.New("orm: the model %s was not updated because there were no changes")
)

Functions

func OrmToFieldLevel

func OrmToFieldLevel(field string, orm Interface) valid.FieldLevel

func Register

func Register(name string, strategy Strategy) error

Register the strategy If the strategy name is empty or already exists a error will return

func RegisterModels

func RegisterModels(model ...Interface)

func SanitizeToString

func SanitizeToString(i interface{}) (string, error)

func SanitizeValue

func SanitizeValue(i interface{}) (interface{}, error)

SanitizeValue is converting any int and nullint to int64 and nullString to string.

func SetReflectValue

func SetReflectValue(field reflect.Value, value reflect.Value) error

SetReflectValue is a helper to set the fields value without worrying about the field type. The field type and the value type must be the same with the exception of int. Int32,int64 and nullInt will be mapped. TODO create a better solution for this, what with int8,int16,uint,...

func ValidateUnique

func ValidateUnique(fl valid.FieldLevel) bool

noDbEntryExists checks if the entered value already exists in the database. The Parameter "exclude" can be used to automatically exclude the actual primary key(s).

func ValidateValuer

func ValidateValuer(field reflect.Value) interface{}

ValidateValuer is needed for the NullInt,NullString,.. struct. It implements the valid.CustomTypeFunc interface.

Types

type ChangedValue

type ChangedValue struct {
	Field        string
	OldV         interface{}
	NewV         interface{}
	Operation    string
	Index        interface{} // On delete index is used as ID field.
	ChangedValue []ChangedValue
}

ChangedValue keeps recursively information of changed values.

type Field

type Field struct {
	Name string

	SqlSelect   string
	Permission  Permission
	Information sqlquery.Column

	Validator *validator
	Custom    bool // defines if the Field is not in the database table.
}

Field is holding some struct field information.

type Interface

type Interface interface {
	Init(c Interface) error

	Cache() (cache.Interface, time.Duration, error)
	SetCache(p cache.Interface, duration time.Duration) error

	WBList() (policy int, fields []string)
	SetWBList(policy int, fields ...string)

	// Default values
	// TODO move to scope?
	DefaultLogger() *logger.Logger
	DefaultCache() (manager cache.Interface, ttl time.Duration, error error)
	DefaultBuilder() (sqlquery.Builder, error)
	DefaultTableName() string
	DefaultDatabaseName() string
	DefaultSchemaName() string
	DefaultStrategy() string
	SoftDelete() (field string, deleteValue interface{}, activeValue []string)

	Scope() *Scope

	First(c *sqlquery.Condition) error
	All(result interface{}, c *sqlquery.Condition) error
	Create() error
	Update() error
	Delete() error
	Count(c *sqlquery.Condition) (int, error)

	// experimental TODO: pass it to the child relations to guarantee its working recursively.
	// at the moment its only working depth 1
	SetRelationCondition(string, sqlquery.Condition)
	// contains filtered or unexported methods
}

func RegisteredModels

func RegisteredModels() []Interface

type JoinTable

type JoinTable struct {
	Name                  string
	ForeignKey            string
	AssociationForeignKey string
}

JoinTable holds the information for the m2m junction table. The name, foreignKey and associationForeignKey are the direct column names of the db table.

type Model

type Model struct {

	// Embedded time fields
	CreatedAt *NullTime `orm:"permission:w" json:",omitempty"`
	UpdatedAt *NullTime `orm:"permission:w" json:",omitempty"`
	DeletedAt *NullTime `orm:"permission:w" json:",omitempty"`
	// contains filtered or unexported fields
}

func (*Model) All

func (m *Model) All(result interface{}, c *sqlquery.Condition) error

All will return all rows by its condition and puts it in the given result. Everything handled in the loading strategy. It will return an error if the model is not initialized or the strategy returns an error.

func (*Model) Cache

func (m *Model) Cache() (cache.Interface, time.Duration, error)

Cache returns the given cache. If none was defined yet the model default ist set. If no cache provider was defined, an error will return.

func (*Model) Count

func (m *Model) Count(c *sqlquery.Condition) (int, error)

Count the existing rows by the given condition.

func (*Model) Create

func (m *Model) Create() (err error)

Create an entry with the actual struct value. Everything handled in the loading strategy. If there is no custom transaction added, it will add one by default and also commits it automatically if everything is ok. Otherwise a Rollback will be called. It will return an error if the model is not initialized, tx error, the strategy returns an error or a commit error happens.

func (Model) DefaultBuilder

func (m Model) DefaultBuilder() (sqlquery.Builder, error)

DefaultBuilder returns the GlobalBuilder.

func (Model) DefaultCache

func (m Model) DefaultCache() (cache.Interface, time.Duration, error)

DefaultCache returns the server cache. Error will return if no default cache is set.

func (Model) DefaultDatabaseName

func (m Model) DefaultDatabaseName() string

DefaultDatabaseName returns the configured database of the builder.

func (Model) DefaultLogger

func (m Model) DefaultLogger() *logger.Logger

DefaultLogger returns the global model logger.

func (Model) DefaultSchemaName

func (m Model) DefaultSchemaName() string

DefaultSchemaName returns the configured schema of the builder.

func (Model) DefaultStrategy

func (m Model) DefaultStrategy() string

DefaultStrategy return the default database strategy.

func (Model) DefaultTableName

func (m Model) DefaultTableName() string

DefaultTableName returns the struct name pluralized in snake_case.

func (*Model) Delete

func (m *Model) Delete() (err error)

Delete the orm model by its primary keys. Error will return if no primaries are set.

func (*Model) First

func (m *Model) First(c *sqlquery.Condition) error

First will check the first founded row by its condition and adds it values to the struct fields. Everything handled in the loading strategy. It will return an error if the model is not initialized or the strategy returns an error.

func (*Model) Init

func (m *Model) Init(c Interface) error

Init the orm model. This method must be called before the orm functions can be used. All mandatory configs will be checked (Cache, Builder, DB, Table name). The struct gets initialized and all relations and fields gets created. The database is checked against the fields and relations. After the init the orm model gets cached for performance reasons.

func (*Model) RelationCondition

func (m *Model) RelationCondition(relation string) *sqlquery.Condition

RelationCondition returns the defined relation condition if set by the user.

func (*Model) Scope

func (m *Model) Scope() *Scope

Scope of the model.

func (*Model) SetCache

func (m *Model) SetCache(c cache.Interface, ttl time.Duration) error

SetCache sets a custom cache to the orm model. The method must be called before the orm model is initialized. Error will return if the cache provider is nil, no time duration is set or the model was already initialized.

func (*Model) SetRelationCondition

func (m *Model) SetRelationCondition(relation string, condition sqlquery.Condition)

SetRelationCondition can set a custom sqlquery.Condition for the relation. Dot notation can be used to access child relations.

func (*Model) SetWBList

func (m *Model) SetWBList(p int, fields ...string)

SetWBList a white/blacklist to the orm.

func (Model) SoftDelete

func (m Model) SoftDelete() (field string, deleteValue interface{}, activeValue []string)

SoftDelete returns the configured schema of the builder. if the activeValue is nil it will perform a "IS NULL" otherwise it will perform a NOT IN

func (*Model) Update

func (m *Model) Update() (err error)

Update an entry with the actual struct value. Everything handled in the loading strategy. If there is no custom transaction added, it will add one by default and also commits it automatically if everything is ok. Otherwise a Rollback will be called. It will return an error if the model is not initialized, tx error, the strategy returns an error or a commit error happens.

func (*Model) WBList

func (m *Model) WBList() (p int, fields []string)

WBList of the orm.

type NullBool

type NullBool struct {
	sql.NullBool
}

func NewNullBool

func NewNullBool(b bool) NullBool

func (NullBool) MarshalJSON

func (b NullBool) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It will encode null if this Bool is null.

func (*NullBool) UnmarshalJSON

func (b *NullBool) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports number and null input. 0 will not be considered a null Bool.

type NullFloat

type NullFloat struct {
	sql.NullFloat64
}

func (NullFloat) MarshalJSON

func (f NullFloat) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It will encode null if this Float is null.

func (NullFloat) MarshalText

func (f NullFloat) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. It will encode a blank string if this Float is null.

func (*NullFloat) UnmarshalJSON

func (f *NullFloat) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports number and null input. 0 will not be considered a null Float.

func (*NullFloat) UnmarshalText

func (f *NullFloat) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler. It will unmarshal to a null Float if the input is blank. It will return an error if the input is not an integer, blank, or "null".

type NullInt

type NullInt struct {
	sql.NullInt64
}

func NewNullInt

func NewNullInt(i int) NullInt

func (NullInt) MarshalJSON

func (i NullInt) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It will encode null if this Int is null.

func (*NullInt) UnmarshalJSON

func (i *NullInt) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports number and null input. 0 will not be considered a null Int. It also supports unmarshalling a sql.NullInt64.

type NullString

type NullString struct {
	sql.NullString
}

func NewNullString

func NewNullString(s string) NullString

func (NullString) MarshalJSON

func (s NullString) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It will encode null if this String is null.

func (NullString) MarshalText

func (s NullString) MarshalText() ([]byte, error)

MarshalText implements encoding.TextMarshaler. It will encode a blank string when this String is null.

func (*NullString) UnmarshalJSON

func (s *NullString) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports string and null input. Blank string input does not produce a null String. It also supports unmarshalling a sql.NullString.

func (*NullString) UnmarshalText

func (s *NullString) UnmarshalText(text []byte) error

UnmarshalText implements encoding.TextUnmarshaler. It will unmarshal to a null String if the input is a blank string.

type NullTime

type NullTime struct {
	sql.NullTime
}

func NewNullTime

func NewNullTime(t time.Time) NullTime

func (NullTime) MarshalJSON

func (t NullTime) MarshalJSON() ([]byte, error)

MarshalJSON implements json.Marshaler. It will encode null if this time is null.

func (*NullTime) UnmarshalJSON

func (t *NullTime) UnmarshalJSON(data []byte) error

UnmarshalJSON implements json.Unmarshaler. It supports string, object (e.g. pq.NullTime and friends) and null input.

type Permission

type Permission struct {
	Read  bool
	Write bool
}

Permission of the field. If read or write is disabled, the database strategy will ignore this field.

type Polymorphic

type Polymorphic struct {
	Field Field
	Type  Field
	Value string
}

Polymorphic is available for hasOne and hasMany relationships.

type Relation

type Relation struct {
	// Type for easier reflection
	Type reflect.Type
	// Kind of the relation (hasOne, hasMany,...)
	Kind string
	// The struct field name
	Field string
	// FK of the main struct
	ForeignKey Field
	// AFK of the child struct
	AssociationForeignKey Field
	// Self referencing relationship
	SelfReference bool
	// Custom struct without orm.Model embedded
	Custom bool

	Permission  Permission
	Validator   *validator
	Polymorphic Polymorphic
	JoinTable   JoinTable
}

Relation keeps some information about the relation type and connection fields.

type Scope

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

Scope is a helper function for the loading strategies or callbacks. Its used to access the internal model fields or relations. Some basic helper functions are defined.

func (Scope) AppendChangedValue

func (scope Scope) AppendChangedValue(cV ChangedValue)

AppendChangedValue adds the changedValue if it does not exist yet by the given field name.

func (Scope) Builder

func (scope Scope) Builder() *sqlquery.Builder

Builder returns a ptr to the orm model builder.

func (Scope) CachedModel

func (scope Scope) CachedModel(model string) (Interface, error)

CachedModel returns a scope to the cached model. Error will return if the cache model was not found.

func (Scope) Caller

func (scope Scope) Caller() Interface

Caller returns the orm caller.

func (Scope) CallerField

func (scope Scope) CallerField(field string) reflect.Value

CallerField return a reflect.Value of the orm caller struct field.

func (Scope) ChangedValueByFieldName

func (scope Scope) ChangedValueByFieldName(field string) *ChangedValue

ChangedValueByName returns a *changedValue by the field name. Nil will return if it does not exist.

func (Scope) Columns

func (scope Scope) Columns(p Permission, SqlSelect bool) []string

Columns return all columns as string by the given permission. SqlSelect indicates if the real column name should be returned or the modified sql select.

func (Scope) EqualWith

func (scope Scope) EqualWith(snapshot Interface) ([]ChangedValue, error)

EqualWith checks if the given orm model is equal with the scope orm model. A []ChangedValue will return with all the changes recursively (fields and relations). On relations and slices the operation info (create, update or delete) is given. All time fields are excluded of this check. On hasMany or m2m relations on DELETE operation the index will be the Field "ID". TODO: check for the real primary field(s) and set the correct index. TODO: id on DELETE no Primary is given, 0 will be set as index. Throw error?

func (Scope) Field

func (scope Scope) Field(name string) (*Field, error)

Field by the given name. No specific permission is checked. No need for it yet. Error will return if it does not exist.

func (Scope) Fields

func (scope Scope) Fields(p Permission) []Field

Fields return all Fields by the given permission. Custom fields are skipped.

func (Scope) InitCallerRelation

func (scope Scope) InitCallerRelation(relField string, noParent bool) (Interface, error)

InitCallerRelation returns an orm.Interface of the given relation Field. If the caller field is an Ptr or struct the reference will be taken and initialized. If the caller field is a slice the struct will be returned and initialized. The new relation model will be initialized with the parent cache, white/blacklist, loopDetection and builder.

func (Scope) InitRelation

func (scope Scope) InitRelation(relationI Interface, relationField string) error

InitRelation initializes the given relation. * If the relation is already initialized, the caller gets set. Otherwise the cache will be set and the orm model gets initialized. * If the argument relationField is not empty, its a child orm model and the parent will be set. * parent wb list, loopDetection and the builder will be passed to the child of the scope orm model.

func (Scope) IsEmpty

func (scope Scope) IsEmpty(perm Permission) bool

IsEmpty checks if the orm model fields and relations are empty by the given permission.

func (Scope) IsPolymorphic

func (scope Scope) IsPolymorphic(relation Relation) bool

IsPolymorphic checks if the given relation is polymorphic.

func (Scope) Model

func (scope Scope) Model() *Model

Model returns a ptr to the orm model.

func (Scope) Name

func (scope Scope) Name(ns bool) string

Name returns the orm model name. Namespace will be included if 'ns' is true. If no namespace is required the orm model name will be titled.

func (Scope) NewScopeFromType

func (scope Scope) NewScopeFromType(p reflect.Type) (*Scope, error)

NewScopeFromType is used to create a new orm instance of the given type. The given type must be the same type as the scope where its getting called because the fields/relations are getting copied.

The cache will be passed from the scope orm. The fields and relations are copied from the active scope orm instance, because there could have been some permission changes. Only used in eager.all.

func (Scope) Parent

func (scope Scope) Parent(name string) (*Model, error)

Parent returns the parent model by name or the root parent if the name is empty. The name must be the orm struct name incl. namespace. Error will return if no parent exists or the given name does not exist.

func (Scope) Parents

func (scope Scope) Parents() []string

Parent returns the parent model by name or the root parent if the name is empty. The name must be the orm struct name incl. namespace. Error will return if no parent exists or the given name does not exist.

func (Scope) PrimariesSet

func (scope Scope) PrimariesSet() bool

PrimariesSet checks if all primaries have a non zero value.

func (Scope) PrimaryKeys

func (scope Scope) PrimaryKeys() []Field

PrimaryKeys return all primary keys as []Field.

func (Scope) PrimaryKeysFieldName

func (scope Scope) PrimaryKeysFieldName() []string

PrimaryKeysFieldName return all primary keys by the field name as string.

func (Scope) ReferencesOnly

func (scope Scope) ReferencesOnly() bool

ReferencesOnly returns the model configuration.

func (Scope) Relation

func (scope Scope) Relation(relation string, p Permission) (Relation, error)

Relation by name. Error will return if the relation does not exist.

func (Scope) Relations

func (scope Scope) Relations(p Permission) []Relation

Relations return all relations of the orm by the given permission. Custom relations are skipped.

func (Scope) ScanValues

func (scope Scope) ScanValues(p Permission) []interface{}

ScanValues, scans a db row into the orm fields.

func (Scope) SetBackReference

func (scope Scope) SetBackReference(rel Relation) error

SetBackReference sets a back reference if the model was already loaded. This will avoid loops. At the moment only on hasOne and belongsTo relations possible.

TODO: create back referencing for m2m.

func (Scope) SetChangedValues

func (scope Scope) SetChangedValues(cV []ChangedValue)

SetChangedValues sets the changedValues field of the scope. This is used to pass the values to a child orm model.

func (Scope) SetParent

func (scope Scope) SetParent(m *Model)

SetParent adds a parent link.

func (Scope) SetReferencesOnly

func (scope Scope) SetReferencesOnly(refOnly bool)

SetReferencesOnly creates/updates only the foreign keys on belongsTo and m2m relations.

func (Scope) SetWhitelistExplict

func (scope Scope) SetWhitelistExplict(b bool)

SetWhitelistExplict sets the whitelist on self referencing models that you have to explicit set the child fields. Example: Role.Subrole.Subrole.Name would only set Role.Subrole.Subrole.Name field to the whitelist. Default if Name is in the whitelist, name will be loaded on every Subrole.

func (Scope) Snapshot

func (scope Scope) Snapshot() Interface

SetParent adds a parent link.

func (Scope) TableName

func (scope Scope) TableName() string

TableName returns the full qualified table name. TODO schema is missing

func (Scope) TakeSnapshot

func (scope Scope) TakeSnapshot()

TakeSnapshot will request the database before an update is made, to only update changed data.

func (Scope) TimeFields

func (scope Scope) TimeFields(p Permission) []string

TimeFields return the existing time fields of the database by the given permission.

func (Scope) UnsetParent

func (scope Scope) UnsetParent()

UnsetParent removes the parent link on the orm model. Useful on self referencing relations.

type Strategy

type Strategy interface {
	First(*Scope, *sqlquery.Condition, Permission) error
	All(interface{}, *Scope, *sqlquery.Condition) error
	Create(*Scope) error
	Update(*Scope, *sqlquery.Condition) error
	Delete(*Scope, *sqlquery.Condition) error
}

Strategy interface

func NewStrategy

func NewStrategy(name string) (Strategy, error)

NewStrategy returns the strategy

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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