gdal

package module
v0.1.14 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2024 License: MIT Imports: 17 Imported by: 0

README

GDAL

go report card test status MIT license Go.Dev reference

A thoroughly object-relation mapping framework based on GORM. Struct object is all you need.

Installation

requirements: go >= 1.18

go get github.com/dirac-lee/gdal

How To Use

Reference example for details.

2.1 Definition of 3 business structs
2.1.1 Business structs
  • PO:DB row persistent struct, mapped as a row of a DB table by tag gorm.
  • Where:DB row selector struct, mapped as sql where condition by tag sql_field and sql_operator.
  • Update: DB row updater struct, mapped as sql update rule by tag sql_field and sql_expr.

⚠️ Caution:the fields of Where 与 Update must be pointer. You can use gptr to simplify the operation。

2.1.2 Examples of business structs
package model

import "time"

// User db model struct, will be mapped to row of db by ORM.
type User struct {
	ID         int64     `gorm:"column:id"`
	Name       string    `gorm:"column:name"`
	Balance    int64     `gorm:"column:balance"`
	CreateTime time.Time `gorm:"column:create_time"`
	UpdateTime time.Time `gorm:"column:update_time"`
	Deleted    bool      `gorm:"column:deleted"`
}

// TableName the corresponding table name of User model struct
func (po User) TableName() string {
	return "user"
}

// UserWhere db where struct, will be mapped to SQL where condition by ORM.
type UserWhere struct {
	ID           *int64     `sql_field:"id" sql_operator:"="`
	IDIn         []int64    `sql_field:"id" sql_operator:"in"`
	Name         *string    `sql_field:"name" sql_operator:"="`
	NameLike     *string    `sql_field:"name" sql_operator:"like"`
	CreateTimeGT *time.Time `sql_field:"create_time" sql_operator:">"`
	Deleted      *bool      `sql_field:"deleted" sql_operator:"="`
}

type UserUpdate struct {
	ID           *int64     `sql_field:"id"`
	Name         *string    `sql_field:"name"`
	Balance      *int64     `gorm:"column:balance"`
	BalanceAdd   *int64     `gorm:"column:balance" sql_expr:"+"`
	BalanceMinus *int64     `gorm:"column:balance" sql_expr:"-"`
	UpdateTime   *time.Time `sql_field:"update_time"`
	Deleted      *bool      `sql_field:"deleted"`
}
2.1.3 Features of Where
  • Use tag sql_field tag to indicate the corresponding table column:
    • sql_field:"id" ➡️ where id = ?
    • sql_field:"dog.id" ➡️ where dog.id = ?
  • Use tag sql_operator to indicate the selecting operator on the column:
    • sql_operator:"=" ➡️ where name = ?,默认
    • sql_operator:">" ➡️ where age > ?
    • sql_operator:">=" ➡️ where age >= ?
    • sql_operator:"<" ➡️ where age < ?
    • sql_operator:"<=" ➡️ where age <= ?
    • sql_operator:"!=" ➡️ where age != ?
    • sql_operator:"null", the type of field must be *bool, and
      • true ➡️ where age is null
      • false ➡️ where age is not null
    • sql_operator:"in" ➡️ where id in (?)

      ⚠️ Caution: empty slice []T{} will be treated as nil slice []T(nil)

    • sql_operator:"not in" ➡️ where id not in (?)

      ⚠️ Caution: the same as in

    • sql_operator:"like" ➡️ (where name like ?, name)
    • sql_operator:"left like" ➡️ (where name like ?, "%"+name)
    • sql_operator:"right like" ➡️ (where name like ?, name+"%")
    • sql_operator:"full like" ➡️ (where name like ?, "%"+name+"%")
    • sql_operator:"json_contains" ➡️ "where JSON_CONTAINS(name, ?)"
    • sql_operator:"json_contains any" ➡️ "where (JSON_CONTAINS(name, ?) or JSON_CONTAINS(name, ?))"
    • sql_operator:"json_contains all" ➡️ "where (JSON_CONTAINS(name, ?) and JSON_CONTAINS(name, ?))"
  • Use tag sql_expr tag to indicate special expressions:
    • sql_expr:"$or" ➡️ or
      • effective when there is no tag sql_field
      • if it has tag sql_field, the tag must be formed as sql_field:"-"
      • the type of field must be []Where
      • connect current Where and elem of the []Where with or
2.1.4 Features of Update
  • Use tag sql_field tag to indicate the corresponding table column:
    • sql_field:"id" ➡️ where id = ?
  • Use tag sql_expr to indicate special expressions:
    • sql_expr:"+" ➡️ update count = count + ?
    • sql_expr:"-" ➡️ update count = count - ?
    • sql_expr:"json_set" ➡️ update JSON_SET(data, $.attr, ?)
2.2 Customize business DAL

Embed *GDAL into business DAL, and indicate the 3 business structs。

package dal

import (
	"github.com/dirac-lee/gdal"
	"github.com/dirac-lee/gdal/example/dal/model"
	"gorm.io/gorm"
)

type UserDAL struct {
	*gdal.GDAL[model.User, model.UserWhere, model.UserUpdate]
}

func NewUserDAL(tx *gorm.DB) *UserDAL {
	return &UserDAL{
		gdal.NewGDAL[model.User, model.UserWhere, model.UserUpdate](tx),
	}
}
2.3 Execute CRUD
2.3.1 Initialize business DAL
package main

import (
	"context"
	"github.com/dirac-lee/gdal/example/dal"
	"github.com/dirac-lee/gdal/example/dal/model"
	"github.com/dirac-lee/gdal/gutil/gptr"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
)

const (
	DemoDSN = "demo"
)

func main() {
	db, err := gorm.Open(mysql.Open(DemoDSN))
	if err != nil {
		panic(err)
	}

	ctx := context.Background()
	gdal := dal.NewUserDAL(db)

}
2.3.2 Create

Create single record

now := time.Now()
    po := model.User{
    ID:         110,
    Name:       "dirac",
    Balance:    100,
    CreateTime: now,
    UpdateTime: now,
    Deleted:    false,
}
gdal.Create(ctx, &po)

Create multiple records

now := time.Now()
pos := []*model.User{
    {
        ID:         120,
        Name:       "bob",
        Balance:    100,
        CreateTime: now,
        UpdateTime: now,
        Deleted:    false,
    },
    {
        ID:         130,
        Name:       "estele",
        Balance:    50,
        CreateTime: now,
        UpdateTime: now,
        Deleted:    false,
    },
}
gdal.MCreate(ctx, &pos)
2.3.3 Delete

Delete physically

where := &model.UserWhere{
    IDIn: []int64{110, 120},
}
gdal.Delete(ctx, where)

Delete physically by ID

gdal.DeleteByID(ctx, 130)
2.3.4 Update

Update

where := &model.UserWhere{
    IDIn: []int64{110, 120},
}
update := &model.UserUpdate{
    BalanceAdd: gptr.Of[int64](10),
}
gdal.Update(ctx, where, update)

Update by ID

update := &model.UserUpdate{
    BalanceMinus: gptr.Of[int64](20),
}
gdal.UpdateByID(ctx, 130, update)
2.3.5 Query

Query normally

var pos []*model.User
where := &model.UserWhere{
    NameLike: gptr.Of("dirac"),
}
err = gdal.Find(ctx, &pos, where)

Query multiple records

where := &model.UserWhere{
    IDIn: []int64{110, 120},
}
pos, err := gdal.MQuery(ctx, where)

Query multiple records by pagination (method 1)

where := &model.UserWhere{
    IDIn: []int64{110, 120},
}
pos, total, err := gdal.MQueryByPaging(ctx, where, gptr.Of[int64](5), nil, gptr.Of("create_time desc"))

Query multiple records by pagination (method 2)

where := &model.UserWhere{
    IDIn: []int64{110, 120},
}
pos, total, err := userDAL.MQueryByPagingOpt(ctx, where, gdal.WithLimit(5), gdal.WithOrder("create_time desc"))
2.3.6 Transaction
db.Transaction(func (tx *gorm.DB) error {
    
    update := &model.UserUpdate{
        BalanceMinus: gptr.Of[int64](20),
    }
    err := userDAL.WithTx(tx).UpdateByID(ctx, 130, update)
    if err != nil {
        return err // rollback
    }
    
    _, err = userDAL.WithTx(tx).DeleteByID(ctx, 130)
    if err != nil {
        return err // rollback
    }
    
    return nil // commit
})
2.3 Efficiency Features
2.3.1 Inject Default
// InjectDefault if you not set field `Deleted` of `UserWhere`,
// the where condition "deleted = false" will be automatically
// injected to the SQL.
func (where *UserWhere) InjectDefault() {
	where.Deleted = gptr.Of(false)
}

then

var pos []*model.User
where := &model.UserWhere{
    NameLike: gptr.Of("dirac"),
}
err := userDAL.Find(ctx, &pos, where)

will be mapped into SQL

SELECT `id`,`name`,`balance`,`hobbies`,`create_time`,`update_time`,`deleted` FROM `user` WHERE (`name` LIKE '%dirac%' AND `deleted` = false)
2.3.2 Force Index
// ForceIndex if field ID or IDIn is set, clause `USE INDEX "PRIMARY"`
// will be automatically injected to the SQL.
func (where UserWhere) ForceIndex() string {
    if where.ID != nil || len(where.IDIn) > 0 {
        return "PRIMARY" // USE INDEX "PRIMARY"
    }
    return "" // no USE INDEX
}

then

where := &model.UserWhere{
    IDIn:     []int64{110, 120},
    NameLike: gptr.Of("tel"),
}
pos, err := userDAL.MQuery(ctx, where, gdal.WithMaster())

will be mapped to SQL (also influenced by default of where deleted)

SELECT `id`,`name`,`balance`,`hobbies`,`create_time`,`update_time`,`deleted` FROM `user` USE INDEX (`PRIMARY`) WHERE (`id` IN (110,120) AND `name` LIKE '%tel%' AND `deleted` = false)
2.3.3 Clauses
now := time.Now()
hobbies, _ := json.Marshal([]string{"cooking", "coding"})
    po := model.User{
    ID:         110,
    Name:       "dirac",
    Balance:    100,
    Hobbies:    string(hobbies),
    CreateTime: now,
    UpdateTime: now,
    Deleted:    false,
}
err := userDAL.Clauses(clause.OnConflict{UpdateAll: true}).Create(ctx, &po)

will be mapped into SQL

INSERT INTO `user` (`name`,`balance`,`hobbies`,`create_time`,`update_time`,`deleted`,`id`) VALUES ('dirac',100,'["cooking","coding"]','2023-07-14 21:29:08.302','2023-07-14 21:29:08.302',false,110) ON DUPLICATE KEY UPDATE `name`=VALUES(`name`),`balance`=VALUES(`balance`),`hobbies`=VALUES(`hobbies`),`create_time`=VALUES(`create_time`),`update_time`=VALUES(`update_time`),`deleted`=VALUES(`deleted`)

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func GetSelectorFromPOs

func GetSelectorFromPOs(pos any) ([]string, error)

GetSelectorFromPOs read pos read gorm tag from pos, then build []string of selector

Types

type DAL

type DAL interface {
	Create(ctx context.Context, po any) error
	Save(ctx context.Context, po any) (int64, error)
	Delete(ctx context.Context, po any, where any) (int64, error)
	Update(ctx context.Context, po any, where any, update any) (int64, error)
	Find(ctx context.Context, po any, where any, options ...QueryOption) (err error)
	First(ctx context.Context, po, where any, options ...QueryOption) error
	Count(ctx context.Context, po any, where any, options ...QueryOption) (int32, error)
	Exist(ctx context.Context, po any, where any, options ...QueryOption) (bool, error)
	DBWithCtx(ctx context.Context, options ...QueryOption) *gorm.DB
	DB(options ...QueryOption) *gorm.DB
}

DAL Data Access Layer.

func NewDAL

func NewDAL(tx *gorm.DB) DAL

NewDAL new dal.

type ForceIndexer

type ForceIndexer interface {
	ForceIndex() string
}

ForceIndexer assign force index for Where. no force index when return "" or unimplemented.

⚠️ WARNING: please implement ForceIndexer for Where in spite of *Where

type GDAL

type GDAL[PO schema.Tabler, Where any, Update any] struct {
	DAL
}

GDAL Generic Data Access Layer. Business DAL should embed *GDAL,and assign PO、Where and Update struct,so that you can extend or override the methods as you will.

💡 HINT: *Where can implement interface InjectDefaulter so that we can inject the customized default value into struct `where` when you query or update.

💡 HINT: Where can implement interface ForceIndexer, if so, we will force index when you query.

⚠️ WARNING: PO must implement interface Tabler and set the corresponding table name.

⚠️ WARNING: Fields of PO mapping to column must include tag `gorm:"column:{{column_name}}"` where `{{}}` represents placeholder, so we can know which columns you need.

🚀 example:

type User struct {
	ID         int64      `gorm:"column:id"`
	Name       string     `gorm:"column:name"`
	Age        uint       `gorm:"column:age"`
	Birthday   *time.Time `gorm:"column:birthday"`
	CompanyID  *int       `gorm:"column:company_id"`
	ManagerID  *uint      `gorm:"column:manager_id"`
	Active     bool       `gorm:"column:active"`
	CreateTime time.Time  `gorm:"column:create_time"`
	UpdateTime time.Time  `gorm:"column:update_time"`
	IsDeleted  bool       `gorm:"column:is_deleted"`
}

func (u User) TableName() string {
	return "user"
}

type UserWhere struct {
	ID        *int64  `sql_field:"id"`
	Name      *string `sql_field:"name"`
	Age       *uint   `sql_field:"age"`
	CompanyID *int    `sql_field:"company_id"`
	ManagerID *uint   `sql_field:"manager_id"`
	Active    *bool   `sql_field:"active"`
	IsDeleted *bool   `sql_field:"is_deleted"`

	BirthdayGE   *time.Time `sql_field:"birthday" sql_operator:">="`
	BirthdayLT   *time.Time `sql_field:"birthday" sql_operator:"<"`
	CreateTimeGE *time.Time `sql_field:"create_time" sql_operator:">="`
	CreateTimeLT *time.Time `sql_field:"create_time" sql_operator:"<"`
	UpdateTimeGE *time.Time `sql_field:"update_time" sql_operator:">="`
	UpdateTimeLT *time.Time `sql_field:"update_time" sql_operator:"<"`

	CompanyIDIn []int  `sql_field:"company_id" sql_operator:"in"`
	ManagerIDIn []uint `sql_field:"manager_id" sql_operator:"in"`
}

func (where UserWhere) ForceIndex() string {
	if where.ID != nil {
		return "id"
	}
	return ""
}

func (where *UserWhere) InjectDefault() {
	where.IsDeleted = gptr.Of(false)
}

type UserUpdate struct {
	ID         *int64     `sql_field:"id"`
	Name       *string    `sql_field:"name"`
	Age        *uint      `sql_field:"age"`
	Birthday   *time.Time `sql_field:"birthday"`
	CompanyID  *int       `sql_field:"company_id"`
	ManagerID  *uint      `sql_field:"manager_id"`
	Active     *bool      `sql_field:"active"`
	CreateTime *time.Time `sql_field:"create_time"`
	UpdateTime *time.Time `sql_field:"update_time"`
	IsDeleted  *bool      `sql_field:"is_deleted"`
}

type UserDAL struct {
	*gdal.GDAL[model.User, model.UserWhere, model.UserUpdate]
}

func NewGDAL

func NewGDAL[PO schema.Tabler, Where any, Update any](tx *gorm.DB) *GDAL[PO, Where, Update]

NewGDAL new GDAL

func (*GDAL[PO, Where, Update]) Clauses added in v0.1.8

func (gdal *GDAL[PO, Where, Update]) Clauses(conds ...clause.Expression) *GDAL[PO, Where, Update]

Clauses generate a new GDAL with clause supplemented.

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) Count

func (gdal *GDAL[PO, Where, Update]) Count(ctx context.Context, where *Where, options ...QueryOption) (int64, error)

Count

💡 HINT:

⚠️ WARNING:

🚀 example:

where := &tests.UserWhere{
	Active:     gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
count, err := UserDAL.Count(ctx, where)

SQL: SELECT count(*) FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= "1999-01-01 00:00:00" and `birthday` < "2019-01-01 00:00:00"

func (*GDAL[PO, Where, Update]) Create

func (gdal *GDAL[PO, Where, Update]) Create(ctx context.Context, po *PO) error

Create insert a single record.

💡 HINT: the po should be a pointer so that we can inject the returning primary key.

💡 HINT: if you want to insert multiple records, use MCreate.

🚀 example:

user := tests.User{
Name:       "Ella",
Age:        17,
Birthday:   gptr.Of(time.Date(1999, 1, 1, 1, 0, 0, 0, time.Local)),
CompanyID:  gptr.Of(110),
ManagerID:  gptr.Of[uint](210),
Active:     true,
CreateTime: time.Now(),
UpdateTime: time.Now(),
IsDeleted:  false,
}
UserDAL.Create(ctx, &user)

SQL: INSERT INTO `user` (`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted`) VALUES ("Ella",17,"1999-01-01 01:00:00",110,210,true,"2023-06-11 09:38:14.483","2023-06-11 09:38:14.483",false) RETURNING `id`Ï

func (*GDAL[PO, Where, Update]) DB

func (gdal *GDAL[PO, Where, Update]) DB(options ...QueryOption) *gorm.DB

DB get embedded DB

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) DBWithCtx

func (gdal *GDAL[PO, Where, Update]) DBWithCtx(ctx context.Context, options ...QueryOption) *gorm.DB

DBWithCtx get embedded DB with context

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) Delete

func (gdal *GDAL[PO, Where, Update]) Delete(ctx context.Context, where *Where) (int64, error)

Delete deletes physically by condition

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) DeleteByID

func (gdal *GDAL[PO, Where, Update]) DeleteByID(ctx context.Context, id int64) (int64, error)

DeleteByID deletes physically by primary key

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) Find

func (gdal *GDAL[PO, Where, Update]) Find(ctx context.Context, pos any, where any, options ...QueryOption) error

Find query by condition with paging options.

💡 HINT: this is the most primary multiple query in GDAL, on which other multiple query methods are based.

⚠️ WARNING: `pos` must be a pointer to (sub-)persistent objects. Fields mapping to column must include tag `gorm:"column:{{column_name}}"` where `{{}}` represents placeholder, so we can know which columns you need.

🚀 example:

var users []User
where := &UserWhere {
	Active: gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
err := userDAL.Find(ctx, &users, where, gdal.WithLimit(10), gdal.WithOrder("birthday"))

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= '1999-01-01 00:00:00' and `birthday` < '2019-01-01 00:00:00' ORDER BY birthday LIMIT 10

func (*GDAL[PO, Where, Update]) First

func (gdal *GDAL[PO, Where, Update]) First(ctx context.Context, po any, where any, options ...QueryOption) error

First query the first record by condition

💡 HINT: this is the most primary single query in GDAL, on which other single query methods are based.

⚠️ WARNING: `po` must be a pointer to a (sub-)persistent object. Fields mapping to column must include tag `gorm:"column:{{column_name}}"` where `{{}}` represents placeholder, so we can know which columns you need.

🚀 example:

var user User
where := &UserWhere {
	Active: gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
err := userDAL.First(ctx, &user, where, gdal.WithOrder("birthday"))

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= '1999-01-01 00:00:00' and `birthday` < '2019-01-01 00:00:00' ORDER BY birthday LIMIT 1

func (*GDAL[PO, Where, Update]) MCreate

func (gdal *GDAL[PO, Where, Update]) MCreate(ctx context.Context, pos *[]*PO) (int64, error)

MCreate insert multiple records.

💡 HINT: the pos should be a pointer to slice so that we can inject the returning primary keys.

🚀 example:

users := []*tests.User{
	GetUser("find"),
	GetUser("find"),
	GetUser("find"),
}

_, err := UserDAL.MCreate(ctx, &users)

SQL: INSERT INTO `user` (`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted`) VALUES ("find",18,"2023-06-11 09:38:14",NULL,NULL,false,"2023-06-11 09:38:14.484","2023-06-11 09:38:14.484",false), ("find",18,"2023-06-11 09:38:14",NULL,NULL,false,"2023-06-11 09:38:14.484","2023-06-11 09:38:14.484",false), ("find",18,"2023-06-11 09:38:14",NULL,NULL,false,"2023-06-11 09:38:14.484","2023-06-11 09:38:14.484",false) RETURNING `id`

func (*GDAL[PO, Where, Update]) MQuery

func (gdal *GDAL[PO, Where, Update]) MQuery(ctx context.Context, where *Where, options ...QueryOption) ([]*PO, error)

MQuery query by condition with paging options.

💡 HINT: When you just need complete persistent objects by condition, this method is what you want.

🚀 example:

where := &UserWhere {
	Active: gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
users, err := userDAL.MQuery(ctx, where, gdal.WithLimit(10), gdal.WithOrder("birthday"))

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= '1999-01-01 00:00:00' and `birthday` < '2019-01-01 00:00:00' ORDER BY birthday LIMIT 10

func (*GDAL[PO, Where, Update]) MQueryByIDs

func (gdal *GDAL[PO, Where, Update]) MQueryByIDs(ctx context.Context, ids []int64, options ...QueryOption) ([]*PO, error)

MQueryByIDs query by primary keys.

💡 HINT: When you just need complete persistent objects by primary key list, this method is what you want.

⚠️ WARNING: nothing returns when ids is empty slice.å

🚀 example:

users, err := userDAL.MQueryByIDs(ctx, gslice.Of(123, 456, 789), gdal.WithLimit(10), gdal.WithOrder("birthday"))

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `id` in (123, 456, 789) ORDER BY birthday LIMIT 10

func (*GDAL[PO, Where, Update]) MQueryByPaging

func (gdal *GDAL[PO, Where, Update]) MQueryByPaging(ctx context.Context, where *Where, limit *int64, offset *int64, order *string, options ...QueryOption) ([]*PO, int64, error)

MQueryByPaging query by paging.

💡 HINT: ref Count and Find

⚠️ WARNING: the second return is the number of total records satisfy where condition in spite of limit and offset.

🚀 example:

where := &tests.UserWhere{
	Active:     gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
users, total, err := UserDAL.MQueryByPaging(ctx, where, gptr.Of(10), nil, gptr.Of("birthday"))

SQL: SELECT count(*) FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= "1999-01-01 00:00:00" and `birthday` < "2019-01-01 00:00:00" SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= "1999-01-01 00:00:00" and `birthday` < "2019-01-01 00:00:00" ORDER BY birthday LIMIT 10

func (*GDAL[PO, Where, Update]) MQueryByPagingOpt

func (gdal *GDAL[PO, Where, Update]) MQueryByPagingOpt(ctx context.Context, where *Where, options ...QueryOption) ([]*PO, int64, error)

MQueryByPagingOpt query by paging options.

💡 HINT: ref Count and Find

⚠️ WARNING: the second return is the number of total records satisfy where condition in spite of limit and offset.

🚀 example:

where := &tests.UserWhere{
Active:     gptr.Of(true),
BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
users, total, err := UserDAL.MQueryByPagingOpt(ctx, where, gdal.WithLimit(10), gdal.WithOrder("birthday"))

SQL: SELECT count(*) FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= "1999-01-01 00:00:00" and `birthday` < "2019-01-01 00:00:00" SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= "1999-01-01 00:00:00" and `birthday` < "2019-01-01 00:00:00" ORDER BY birthday LIMIT 10

func (*GDAL[PO, Where, Update]) MSave added in v0.1.10

func (gdal *GDAL[PO, Where, Update]) MSave(ctx context.Context, pos *[]*PO) (int64, error)

MSave saves multiple records, and return success count

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) MUpdate

func (gdal *GDAL[PO, Where, Update]) MUpdate(ctx context.Context, where *Where, update *Update) (int64, error)

MUpdate updates multiple records by condition, return success count

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) MakePO

func (gdal *GDAL[PO, Where, Update]) MakePO() PO

func (*GDAL[PO, Where, Update]) QueryByID

func (gdal *GDAL[PO, Where, Update]) QueryByID(ctx context.Context, id int64, options ...QueryOption) (*PO, error)

QueryByID query the record by primary key

⚠️ WARNING: if primary key is not exist, return nil pointer.

🚀 example:

users, err := UserDAL.QueryByID(ctx, 123)

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `id` = 123 ORDER BY `user`.`id` LIMIT 1

func (*GDAL[PO, Where, Update]) QueryFirst

func (gdal *GDAL[PO, Where, Update]) QueryFirst(ctx context.Context, where *Where, options ...QueryOption) (*PO, error)

QueryFirst query the first record by condition.

💡 HINT: ref First.

🚀 example:

var user User
where := &UserWhere {
	Active: gptr.Of(true),
	BirthdayGE: gptr.Of(time.Date(1999, 1, 1, 0, 0, 0, 0, time.Local)),
	BirthdayLT: gptr.Of(time.Date(2019, 1, 1, 0, 0, 0, 0, time.Local)),
}
user, err := userDAL.QueryFirst(ctx, where, gdal.WithOrder("birthday"))

SQL: SELECT `id`,`name`,`age`,`birthday`,`company_id`,`manager_id`,`active`,`create_time`,`update_time`,`is_deleted` FROM `user` WHERE `active` = true and `is_deleted` = false and `birthday` >= '1999-01-01 00:00:00' and `birthday` < '2019-01-01 00:00:00' ORDER BY birthday LIMIT 1

func (*GDAL[PO, Where, Update]) Save added in v0.1.10

func (gdal *GDAL[PO, Where, Update]) Save(ctx context.Context, po *PO) error

Save saves single record

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) TableName

func (gdal *GDAL[PO, Where, Update]) TableName() string

TableName the corresponding table name

func (*GDAL[PO, Where, Update]) Update

func (gdal *GDAL[PO, Where, Update]) Update(ctx context.Context, where *Where, update *Update) error

Update updates records by condition

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) UpdateByID

func (gdal *GDAL[PO, Where, Update]) UpdateByID(ctx context.Context, id int64, update *Update) error

UpdateByID updates single record by primary key

💡 HINT:

⚠️ WARNING:

🚀 example:

func (*GDAL[PO, Where, Update]) WithTx

func (gdal *GDAL[PO, Where, Update]) WithTx(tx *gorm.DB) *GDAL[PO, Where, Update]

WithTx generate a new GDAL with tx embedded

💡 HINT:

⚠️ WARNING:

🚀 example:

type InjectDefaulter

type InjectDefaulter interface {
	InjectDefault()
}

InjectDefaulter inject default for *Where

⚠️ WARNING: please implement InjectDefaulter for *Where in spite of Where

type QueryConfig

type QueryConfig struct {

	// export field
	Limit   *int
	Offset  *int
	Order   *string
	Selects []string
	// contains filtered or unexported fields
}

func MakeQueryConfig

func MakeQueryConfig(options []QueryOption) *QueryConfig

MakeQueryConfig convert options to QueryConfig

type QueryOption

type QueryOption func(v *QueryConfig)

func WithLimit

func WithLimit(limit int) QueryOption

WithLimit assign limit

func WithMaster

func WithMaster() QueryOption

WithMaster read master

💡 HINT:

⚠️ WARNING:

🚀 example:

func WithOffset

func WithOffset(offset int) QueryOption

WithOffset assign offset

func WithOrder

func WithOrder(order string) QueryOption

WithOrder assign order

func WithSelects

func WithSelects(selects []string) QueryOption

WithSelects assign selected columns

💡 HINT:

⚠️ WARNING:

🚀 example:

Directories

Path Synopsis
dal
gutil

Jump to

Keyboard shortcuts

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