gosql

package module
v1.1.10 Latest Latest
Warning

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

Go to latest
Published: Jun 19, 2019 License: MIT Imports: 16 Imported by: 1

README

gosql

The package based on sqlx, It's simple and keep simple

Build Status codecov Go Report Card
GoDoc

Usage

Connection database and use sqlx original function,See the https://github.com/jmoiron/sqlx

import (
    _ "github.com/go-sql-driver/mysql" //mysql driver
    "github.com/ilibs/gosql"
)

func main(){
    configs := make(map[string]*gosql.Config)

    configs["default"] = &gosql.Config{
        Enable:  true,
        Driver:  "mysql",
        Dsn:     "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8&parseTime=True&loc=Asia%2FShanghai",
        ShowSql: true,
    }

    //connection database
    gosql.Connect(configs)

    gosql.DB().QueryRowx("select * from users where id = 1")
}

Use default database, So you can use wrapper function

//Exec
gosql.Exec("insert into users(name,email,created_at,updated_at) value(?,?,?,?)","test","test@gmail.com",time.Now(),time.Now())

//Queryx
rows,err := gosql.Queryx("select * from users")
for rows.Next() {
    user := &Users{}
    err = rows.StructScan(user)
}

//QueryRowx
user := &Users{}
err := gosql.QueryRowx("select * from users where id = ?",1).StructScan(user)

//Get
user := &Users{}
err := gosql.Get(user,"select * from users where id = ?",1)

//Select
users := make([]*Users)
err := gosql.Select(&users,"select * from users")

//Change database
db := gosql.Use("test")
db.Queryx("select * from tests")

Using struct

type Users struct {
	Id        int       `db:"id"`
	Name      string    `db:"name"`
	Email     string    `db:"email"`
	Status    int       `db:"status"`
	CreatedAt time.Time `db:"created_at"`
	UpdatedAt time.Time `db:"updated_at"`
}

func (u *Users) DbName() string {
	return "default"
}

func (u *Users) TableName() string {
	return "users"
}

func (u *Users) PK() string {
	return "id"
}

//Get
user := &Users{}
gosql.Model(user).Where("id=?",1).Get()

//All
user := make([]*Users,0)
gosql.Model(&user).All()

//Create and auto set CreatedAt
gosql.Model(&User{Name:"test",Email:"test@gmail.com"}).Create()

//Update
gosql.Model(&User{Name:"test2",Email:"test@gmail.com"}).Where("id=?",1).Update()
//If you need to update the zero value, you can do so
gosql.Model(&User{Status:0}).Where("id=?",1).Update("status")

//Delete
gosql.Model(&User{}).Where("id=?",1).Delete()

If you use struct to generate where conditions

//Get where id = 1 and name = "test1"
user := &Users{Id:1,Name:"test1"}
gosql.Model(&user).Get()

//Update default use primary key as the condition
gosql.Model(&User{Id:1,Name:"test2"}).Update()
//Use custom conditions
//Builder => UPDATE users SET `id`=?,`name`=?,`updated_at`=? WHERE (status = ?)
gosql.Model(&User{Id:1,Name:"test2"}).Where("status = ?",1).Update()

//Delete
gosql.Model(&User{Id:1}).Delete()

But the zero value is filtered by default, you can specify fields that are not filtered. For example

user := &Users{Id:1,Status:0}
gosql.Model(&user).Get("status")

You can use the genstruct tool to quickly generate database structs

Transaction

The Tx function has a callback function, if an error is returned, the transaction rollback

gosql.Tx(func(tx *sqlx.Tx) error {
    for id := 1; id < 10; id++ {
        user := &Users{
            Id:    id,
            Name:  "test" + strconv.Itoa(id),
            Email: "test" + strconv.Itoa(id) + "@test.com",
        }

        gosql.Model(user, tx).Create()

        if id == 8 {
            return errors.New("interrupt the transaction")
        }
    }

    //query with transaction
    var num int
    err := gosql.WithTx(tx).QueryRowx("select count(*) from user_id = 1").Scan(&num)

    if err != nil {
        return err
    }

    return nil
})

If you need to invoke context, you can use gosql.Txx

Automatic time

If your fields contain the following field names, they will be updated automatically

AUTO_CREATE_TIME_FIELDS = []string{
    "create_time",
    "create_at",
    "created_at",
    "update_time",
    "update_at",
    "updated_at",
}
AUTO_UPDATE_TIME_FIELDS = []string{
    "update_time",
    "update_at",
    "updated_at",
}

Using Map

Create Update Delete Count support map[string]interface,For example:

//Create
gosql.Table("users").Create(map[string]interface{}{
    "id":         1,
    "name":       "test",
    "email":      "test@test.com",
    "created_at": "2018-07-11 11:58:21",
    "updated_at": "2018-07-11 11:58:21",
})

//Update
gosql.Table("users").Where("id = ?", 1).Update(map[string]interface{}{
    "name":  "fifsky",
    "email": "fifsky@test.com",
})

//Delete
gosql.Table("users").Where("id = ?", 1).Delete()

//Count
gosql.Table("users").Where("id = ?", 1).Count()

//Change database
gosql.Use("db2").Table("users").Where("id = ?", 1).Count()

//Transaction `tx` is *sqlx.Tx
gosql.Table("users",tx).Where("id = ?", 1}).Count()

sql.Null*

Now Model support sql.Null* field's, Note, however, that if sql.Null* is also filtered by zero values,For example

type Users struct {
	Id          int            `db:"id"`
	Name        string         `db:"name"`
	Email       string         `db:"email"`
	Status      int            `db:"status"`
	SuccessTime sql.NullString `db:"success_time" json:"success_time"`
	CreatedAt   time.Time      `db:"created_at" json:"created_at"`
	UpdatedAt   time.Time      `db:"updated_at" json:"updated_at"`
}

user := &Users{
    Id: 1,
    SuccessTime: sql.NullString{
        String: "2018-09-03 00:00:00",
        Valid:  false,
    }
}

err := gosql.Model(user).Get()

Builder SQL:

Query: SELECT * FROM users WHERE (id=?);
Args:  []interface {}{1}
Time:  0.00082s

If sql.NullString of Valid attribute is false, SQL builder will ignore this zero value

gosql.Expr

Reference GORM Expr, Resolve update field self-update problem

gosql.Table("users").Update(map[string]interface{}{
    "id":2,
    "count":gosql.Expr("count+?",1)
})
//Builder SQL
//UPDATE `users` SET `count`=count + ?,`id`=?; [1 2]

"In" Queries

Because database/sql does not inspect your query and it passes your arguments directly to the driver, it makes dealing with queries with IN clauses difficult:

SELECT * FROM users WHERE level IN (?);

sqlx.In is encapsulated In gosql and can be queried using the following schema

var levels = []int{4, 6, 7}
rows, err := gosql.Queryx("SELECT * FROM users WHERE level IN (?);", levels)

//or

user := make([]*Users, 0)
err := gosql.Select(&user, "select * from users where id in(?)",[]int{1,2,3})

Relation

gosql used the golang structure to express the relationships between tables,You only need to use the relation Tag to specify the associated field, see example

type MomentList struct {
	models.Moments
	User   *models.Users    `json:"user" db:"-" relation:"user_id,id"`         //one-to-one
	Photos []*models.Photos `json:"photos" db:"-" relation:"id,moment_id"`     //one-to-many
}

Get single result

moment := &MomentList{}
err := gosql.Model(moment).Where("status = 1 and id = ?",14).Get()
//output User and Photos and you get the result

SQL:

2018/12/06 13:27:54
	Query: SELECT * FROM `moments` WHERE (status = 1 and id = ?);
	Args:  []interface {}{14}
	Time:  0.00300s

2018/12/06 13:27:54
	Query: SELECT * FROM `moment_users` WHERE (id=?);
	Args:  []interface {}{5}
	Time:  0.00081s

2018/12/06 13:27:54
	Query: SELECT * FROM `photos` WHERE (moment_id=?);
	Args:  []interface {}{14}
	Time:  0.00093s

Get list result, many-to-many

var moments = make([]*MomentList, 0)
err := gosql.Model(&moments).Where("status = 1").Limit(10).All()
//You get the total result  for *UserMoment slice

SQL:

2018/12/06 13:50:59
	Query: SELECT * FROM `moments` WHERE (status = 1) LIMIT 10;
	Time:  0.00319s

2018/12/06 13:50:59
	Query: SELECT * FROM `moment_users` WHERE (id in(?));
	Args:  []interface {}{[]interface {}{5}}
	Time:  0.00094s

2018/12/06 13:50:59
	Query: SELECT * FROM `photos` WHERE (moment_id in(?, ?, ?, ?, ?, ?, ?, ?, ?, ?));
	Args:  []interface {}{[]interface {}{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}}
	Time:  0.00087s

Relation Where:

moment := &MomentList{}
err := gosql.Relation("User" , func(b *Builder) {
    //this is builder instance,
    b.Where("gender = 0")
}).Get(moment , "select * from moments")

Hooks

Hooks are functions that are called before or after creation/querying/updating/deletion.

If you have defiend specified methods for a model, it will be called automatically when creating, updating, querying, deleting, and if any callback returns an error, gosql will stop future operations and rollback current transaction.

// begin transaction
BeforeChange
BeforeCreate
// update timestamp `CreatedAt`, `UpdatedAt`
// save
AfterCreate
AfterChange
// commit or rollback transaction

Example:

func (u *Users) BeforeCreate() (err error) {
  if u.IsValid() {
    err = errors.New("can't save invalid data")
  }
  return
}

func (u *Users) AfterCreate(tx *sqlx.tx) (err error) {
  if u.Id == 1 {
    u.Email = "after@test.com"
    Model(u,tx).Update()
  }
  return
}

BeforeChange and AfterChange only used in create/update/delete

All Hooks:

BeforeChange
AfterChange
BeforeCreate
AfterCreate
BeforeUpdate
AfterUpdate
BeforeDelete
AfterDelete
BeforeFind
AfterFind

Hook func type supports multiple ways:

func (u *Users) BeforeCreate()
func (u *Users) BeforeCreate() (err error)
func (u *Users) BeforeCreate(tx *sqlx.Tx)
func (u *Users) BeforeCreate(tx *sqlx.Tx) (err error)

Thanks

sqlx https://github.com/jmoiron/sqlx

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (

	//Insert database automatically updates fields
	AUTO_CREATE_TIME_FIELDS = []string{
		"create_time",
		"create_at",
		"created_at",
		"update_time",
		"update_at",
		"updated_at",
	}
	//Update database automatically updates fields
	AUTO_UPDATE_TIME_FIELDS = []string{
		"update_time",
		"update_at",
		"updated_at",
	}
)
View Source
var Default = "default"

Default set database default tag name

View Source
var FatalExit = true

If database fatal exit

Functions

func Connect

func Connect(configs map[string]*Config) (err error)

Connect database

func DB

func DB(name ...string) *sqlx.DB

DB gets the specified database engine, or the default DB if no name is specified.

func Exec

func Exec(query string, args ...interface{}) (sql.Result, error)

Exec default database

func Expr added in v1.1.10

func Expr(expression string, args ...interface{}) *expr

Expr generate raw SQL expression, for example:

gosql.Table("user").Update(map[string]interface{}{"price", gorm.Expr("price * ? + ?", 2, 100)})

func Get

func Get(dest interface{}, query string, args ...interface{}) error

Get default database

func Import

func Import(f string) ([]sql.Result, error)

Import SQL DDL from io.Reader

func IsZero

func IsZero(val reflect.Value) bool

IsZero assert value is zero value

func List

func List() map[string]*sqlx.DB

List gets the list of database engines

func QueryRowx

func QueryRowx(query string, args ...interface{}) *sqlx.Row

QueryRowx default database

func Queryx

func Queryx(query string, args ...interface{}) (*sqlx.Rows, error)

Queryx default database

func RelationAll added in v1.1.10

func RelationAll(data interface{}, chains map[string]BuilderChainFunc) error

RelationAll is gets the associated relational data for multiple pieces of data

func RelationOne added in v1.1.10

func RelationOne(data interface{}, chains map[string]BuilderChainFunc) error

RelationOne is get the associated relational data for a single piece of data

func Select

func Select(dest interface{}, query string, args ...interface{}) error

Select default database

func SetLogger

func SetLogger(l Logger)

func SetLogging added in v1.0.1

func SetLogging(logging bool)

SetLogging set default logger

func Tx

func Tx(fn func(tx *sqlx.Tx) error) error

Tx default database the transaction

func Txx

func Txx(ctx context.Context, fn func(ctx context.Context, tx *sqlx.Tx) error) error

Txx default database the transaction with context

Types

type Builder

type Builder struct {
	SQLBuilder
	// contains filtered or unexported fields
}

func Model

func Model(model interface{}, tx ...*sqlx.Tx) *Builder

Model construct SQL from Struct

func (*Builder) All

func (b *Builder) All() (err error)

All get data rows from to Struct

func (*Builder) Count

func (b *Builder) Count(zeroValues ...string) (num int64, err error)

gosql.Model(&User{}).Where("status = 0").Count()

func (*Builder) Create

func (b *Builder) Create() (lastInsertId int64, err error)

Create data from to Struct

func (*Builder) Delete

func (b *Builder) Delete(zeroValues ...string) (affected int64, err error)

gosql.Model(&User{Id:1}).Delete()

func (*Builder) ForceIndex added in v1.1.10

func (b *Builder) ForceIndex(i string) *Builder

ForceIndex

func (*Builder) Get

func (b *Builder) Get(zeroValues ...string) (err error)

All get data row from to Struct

func (*Builder) Hint

func (b *Builder) Hint(hint string) *Builder

Hint is set TDDL "/*+TDDL:slave()*/"

func (*Builder) Limit

func (b *Builder) Limit(i int) *Builder

Limit

func (*Builder) Offset

func (b *Builder) Offset(i int) *Builder

Offset

func (*Builder) OrderBy

func (b *Builder) OrderBy(str string) *Builder

OrderBy for example "id desc"

func (*Builder) Relation added in v1.1.10

func (b *Builder) Relation(fieldName string, fn BuilderChainFunc) *Builder

Relation association table builder handle

func (*Builder) Select added in v1.1.10

func (b *Builder) Select(fields string) *Builder

func (*Builder) ShowSQL

func (b *Builder) ShowSQL() *Builder

ShowSQL output single sql

func (*Builder) Update

func (b *Builder) Update(zeroValues ...string) (affected int64, err error)

gosql.Model(&User{Id:1,Status:0}).Update("status")

func (*Builder) Where

func (b *Builder) Where(str string, args ...interface{}) *Builder

Where for example Where("id = ? and name = ?",1,"test")

func (*Builder) WithTx added in v1.1.10

func (b *Builder) WithTx(tx *sqlx.Tx) *Builder

WithTx model use tx

type BuilderChainFunc added in v1.1.10

type BuilderChainFunc func(b *Builder)

type Config

type Config struct {
	Enable       bool   `toml:"enable" json:"enable"`
	Driver       string `toml:"driver" json:"driver"`
	Dsn          string `toml:"dsn" json:"dsn"`
	MaxOpenConns int    `toml:"max_open_conns" json:"max_open_conns"`
	MaxIdleConns int    `toml:"max_idle_conns" json:"max_idle_conns"`
	MaxLifetime  int    `toml:"max_lefttime" json:"max_lefttime"`
	ShowSql      bool   `toml:"show_sql" json:"show_sql"`
}

Config is database connection configuration

type Hook added in v1.0.1

type Hook struct {
	Errs []error
	// contains filtered or unexported fields
}

func NewHook added in v1.0.1

func NewHook(wrapper *Wrapper) *Hook

func (*Hook) Err added in v1.0.1

func (h *Hook) Err(err error) error

Err add error

func (*Hook) Error added in v1.0.1

func (h *Hook) Error() error

Error format happened errors

func (*Hook) HasError added in v1.0.1

func (h *Hook) HasError() int

HasError has errors

type IModel

type IModel interface {
	TableName() string
	DbName() string
	PK() string
}

Model interface

type ISqlx

type ISqlx interface {
	Queryx(query string, args ...interface{}) (*sqlx.Rows, error)
	QueryRowx(query string, args ...interface{}) *sqlx.Row
	Get(dest interface{}, query string, args ...interface{}) error
	Select(dest interface{}, query string, args ...interface{}) error
	Exec(query string, args ...interface{}) (sql.Result, error)
	Rebind(query string) string
}

type Logger

type Logger interface {
	Printf(format string, v ...interface{})
}

Logger represents a logging collector. You can pass a logging collector to gosql.SetLogger(myCollector) to make it collect QueryStatus messages after executing a query.

type Mapper

type Mapper struct {
	SQLBuilder
	// contains filtered or unexported fields
}

func Table

func Table(t string, tx ...*sqlx.Tx) *Mapper

Table select table name

func (*Mapper) Count

func (m *Mapper) Count() (num int64, err error)

Count data from to map[string]interface

func (*Mapper) Create

func (m *Mapper) Create(data map[string]interface{}) (lastInsertId int64, err error)

Create data from to map[string]interface

func (*Mapper) Delete

func (m *Mapper) Delete() (affected int64, err error)

Delete data from to map[string]interface

func (*Mapper) ShowSQL

func (m *Mapper) ShowSQL() *Mapper

func (*Mapper) Update

func (m *Mapper) Update(data map[string]interface{}) (affected int64, err error)

Update data from to map[string]interface

func (*Mapper) Where

func (m *Mapper) Where(str string, args ...interface{}) *Mapper

Where

func (*Mapper) WithTx added in v1.1.10

func (m *Mapper) WithTx(tx *sqlx.Tx) *Mapper

WithTx Table use tx

type QueryStatus

type QueryStatus struct {
	Query string
	Args  interface{}

	Start time.Time
	End   time.Time

	Err error
}

QueryStatus represents the status of a query after being executed.

func (*QueryStatus) String

func (q *QueryStatus) String() string

String returns a formatted log message.

type ReflectMapper

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

func NewReflectMapper

func NewReflectMapper(tagName string) *ReflectMapper

func (*ReflectMapper) FieldByName added in v1.1.10

func (r *ReflectMapper) FieldByName(v reflect.Value, name string) reflect.Value

FieldByName returns a field by its mapped name as a reflect.Value. Panics if v's Kind is not Struct or v is not Indirectable to a struct Kind. Returns zero Value if the name is not found.

func (*ReflectMapper) FieldMap

func (r *ReflectMapper) FieldMap(v reflect.Value) map[string]reflect.Value

FieldMap returns the mapper's mapping of field names to reflect values. Panics if v's Kind is not Struct, or v is not Indirectable to a struct kind.

type SQLBuilder

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

func (*SQLBuilder) Where

func (s *SQLBuilder) Where(str string, args ...interface{})

type Wrapper

type Wrapper struct {
	RelationMap map[string]BuilderChainFunc
	// contains filtered or unexported fields
}

func Relation added in v1.1.10

func Relation(name string, fn BuilderChainFunc) *Wrapper

Relation association table builder handle

func ShowSql

func ShowSql() *Wrapper

func Use

func Use(db string) *Wrapper

Use is change database

func WithTx

func WithTx(tx *sqlx.Tx) *Wrapper

WithTx use the specified transaction session

func (*Wrapper) Exec

func (w *Wrapper) Exec(query string, args ...interface{}) (result sql.Result, err error)

Exec wrapper sqlx.Exec

func (*Wrapper) Get

func (w *Wrapper) Get(dest interface{}, query string, args ...interface{}) (err error)

Get wrapper sqlx.Get

func (*Wrapper) Import

func (w *Wrapper) Import(f string) ([]sql.Result, error)

Import SQL DDL from sql file

func (*Wrapper) QueryRowx

func (w *Wrapper) QueryRowx(query string, args ...interface{}) (rows *sqlx.Row)

QueryRowx wrapper sqlx.QueryRowx

func (*Wrapper) Queryx

func (w *Wrapper) Queryx(query string, args ...interface{}) (rows *sqlx.Rows, err error)

Queryx wrapper sqlx.Queryx

func (*Wrapper) Rebind added in v1.1.10

func (w *Wrapper) Rebind(query string) string

Rebind wrapper sqlx.Rebind

func (*Wrapper) Relation added in v1.1.10

func (w *Wrapper) Relation(name string, fn BuilderChainFunc) *Wrapper

Relation association table builder handle

func (*Wrapper) Select

func (w *Wrapper) Select(dest interface{}, query string, args ...interface{}) (err error)

Select wrapper sqlx.Select

func (*Wrapper) Table

func (w *Wrapper) Table(t string) *Mapper

Table database handler from to table name for example gosql.Use("db2").Table("users")

func (*Wrapper) Tx

func (w *Wrapper) Tx(fn func(tx *sqlx.Tx) error) (err error)

Tx the transaction

func (*Wrapper) Txx

func (w *Wrapper) Txx(ctx context.Context, fn func(ctx context.Context, tx *sqlx.Tx) error) (err error)

Txx the transaction with context

Directories

Path Synopsis
example

Jump to

Keyboard shortcuts

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