Skip to content

cupogo/andvari

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

351 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Andvari

基础模型和数据访问组件

Base model and data access components

三种 Model 主键类型

Model 类型 ID 类型 生成方式 使用场景
DefaultModel OID (字符串) 自动生成 (oid.NewID()) 大多数业务模型
DunceModel 字串 (string) 手动指定 需要业务含义的 ID,如 slug、code
SerialModel 自增序列 (int) 数据库自动递增 历史流水、统计类

Dependencies


Databases

  • PostgreSQL for now

Interfaces

// Changeable can update a model with special columns
type Changeable interface {
	SetChange(...string)
	GetChanges() []string
	CountChange() int
}

// Model based primary key ID
type Model interface {
	GetID() any
	SetID(id any) bool
	IsZeroID() bool
}

type ModelChangeable interface {
	Model
	Changeable
}

type Sortable interface {
	CanSort(key string) bool
}

type Pager interface {
	GetLimit() int
	GetPage() int
	GetSkip() int
	GetSort() string
	GetTotal() int
	SetTotal(n int)
	Sortable
}

// Sifter for select condition
type Sifter interface {
	Sift(q *SelectQuery) *SelectQuery
}

// SifterX with context
type SifterX interface {
	SiftX(ctx context.Context, q *SelectQuery) *SelectQuery
}

type ListArg interface {
	Pager
	Sifter
	Deleted() bool // select from trash schema like soft delete
}

Example

define models

import (
	"github.com/cupogo/andvari/models/comm"
	"github.com/cupogo/andvari/models/oid"
)

// Article 文章
type Article struct {
	comm.BaseModel `bun:"table:cms_article,alias:a" json:"-"`

	comm.DefaultModel

	ArticleBasic
} // @name Article

type ArticleBasic struct {
	// 作者
	Author string `bun:",notnull" extensions:"x-order=A" json:"author"`
	// 标题
	Title string `bun:",notnull" extensions:"x-order=B" json:"title"`
	// 内容
	Content string `bun:",notnull" extensions:"x-order=C" json:"content"`
} // @name ArticleBasic

type Articles []Article

// Creating function call to it's inner fields defined hooks
func (z *Article) Creating() error {
	if z.IsZeroID() {
		z.SetID(oid.NewID(oid.OtArticle))
	}

	return z.DefaultModel.Creating()
}

database prepare testing

CREATE USER testing WITH LOGIN PASSWORD 'develop';
CREATE DATABASE testing WITH OWNER = testing ENCODING = 'UTF8';
GRANT ALL ON DATABASE testing TO testing;

database store open

pgx.RegisterModel((*cms1.Article)(nil))

dsn := "postgres://testing:develop0@localhost/testing?sslmode=disable"
tscfg := "zhcfg"
debug := false
db, err := pgx.Open(dsn ,tscfg, debug)

// create all registered tables
dropIt := false
err = db.InitSchemas(ctx, dropIt)

data access

// custom a Sifter
type ArticleSpec struct {
	pgx.PageSpec // Pager
	pgx.ModelSpec // Sifter

	// 作者
	Author string `extensions:"x-order=A" form:"author" json:"author"`
	// 标题
	Title string `extensions:"x-order=B" form:"title" json:"title"`
}

func (spec *ArticleSpec) Sift(q *ormQuery) *ormQuery {
	q = spec.ModelSpec.Sift(q)
	q, _ = siftICE(q, "author", spec.Author, false)
	q, _ = siftMatch(q, "title", spec.Title, false)

	return q
}
func (spec *ArticleSpec) CanSort(k string) bool {
	switch k {
	case "author":
		return true
	default:
		return spec.ModelSpec.CanSort(k)
	}
}


type contentStore struct {
	w *Wrap // a database wrapper
}

func (s *contentStore) ListArticle(ctx context.Context, spec *ArticleSpec) (data cms1.Articles, total int, err error) {
	total, err = s.w.db.ListModel(ctx, spec, &data)
	return
}
func (s *contentStore) GetArticle(ctx context.Context, id string) (obj *cms1.Article, err error) {
	obj = new(cms1.Article)
	err = s.w.db.GetModel(ctx, obj, id)
	return
}
func (s *contentStore) CreateArticle(ctx context.Context, in cms1.ArticleBasic) (obj *cms1.Article, err error) {
	obj = &cms1.Article{
		ArticleBasic: in,
	}
	err = s.w.db.RunInTx(ctx, nil, func(ctx context.Context, tx pgTx) (err error) {
		if err = dbBeforeSaveArticle(ctx, tx, obj); err != nil {
			return err
		}
		dbOpModelMeta(ctx, tx, obj)
		err = dbInsert(ctx, tx, obj)
		return err
	})
	return
}
func (s *contentStore) UpdateArticle(ctx context.Context, id string, in cms1.ArticleSet) error {
	exist := new(cms1.Article)
	if err := dbGetWithPKID(ctx, s.w.db, exist, id); err != nil {
		return err
	}
	_ = exist.SetWith(in)
	return s.w.db.RunInTx(ctx, nil, func(ctx context.Context, tx pgTx) (err error) {
		if err = dbBeforeSaveArticle(ctx, tx, exist); err != nil {
			return
		}
		dbOpModelMeta(ctx, tx, exist)
		return dbUpdate(ctx, tx, exist)
	})
}
func (s *contentStore) DeleteArticle(ctx context.Context, id string) error {
	obj := new(cms1.Article)
	if err := dbGetWithPKID(ctx, s.w.db, obj, id); err != nil {
		return err
	}
	return s.w.db.RunInTx(ctx, nil, func(ctx context.Context, tx pgTx) (err error) {
		err = dbDeleteT(ctx, tx, s.w.db.Schema(), s.w.db.SchemaCrap(), "cms_article", obj.ID)
		if err != nil {
			return
		}
		return dbAfterDeleteArticle(ctx, tx, obj)
	})
}

About

Base model and data access components

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors