1 Star 0 Fork 0

simon/gomysql

加入 Gitee
与超过 1400万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
db.go 13.68 KB
一键复制 编辑 原始数据 按行查看 历史
simon 提交于 2022-12-31 12:35 +08:00 . 使用说明
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
package mysql
import (
"context"
"database/sql"
"fmt"
"log"
"runtime/debug"
"strconv"
"strings"
"sync"
_ "github.com/go-sql-driver/mysql"
)
type Db struct {
DbConn *DbConnection
// DbQuery DbQuery
Dbconfig *map[string]interface{}
}
//创建连接器
type DbConnection struct {
DB *sql.DB
DbPrefix string
DbName string
DbConf map[string]string
}
//构建查询器
type DbQuery struct {
Wher string
args []interface{}
Joinn string
order string
limit string
alias string
table string
group string
having string
in []interface{}
field string
DB *sql.DB
Rows interface{}
Row interface{}
Prefix string
sync.RWMutex
}
//构建连接
func (DbConnection *DbConnection) Connt(cnt *map[string]string) error {
var build strings.Builder
build.WriteString((*cnt)["username"])
build.WriteString(":")
build.WriteString((*cnt)["password"])
build.WriteString("@")
build.WriteString((*cnt)["network"])
build.WriteString("(")
build.WriteString((*cnt)["server"])
build.WriteString(":")
build.WriteString((*cnt)["port"])
build.WriteString(")/")
build.WriteString((*cnt)["database"])
db, err := sql.Open("mysql", build.String())
if err != nil {
log.Printf("Open mysql failed,err:%v\n", err)
return err
}
DbConnection.DB = db
DbConnection.DbPrefix = (*cnt)["prefix"]
DbConnection.DbName = (*cnt)["database"]
DbConnection.DbConf = (*cnt)
return nil
}
func (db *Db) Db(table string) *DbQuery {
var q = new(DbQuery)
q.Builder(db.DbConn)
if table != "" {
q = q.Table(table)
}
return q
}
func (q *DbQuery) Builder(dbConnection *DbConnection) {
connerr := dbConnection.DB.Ping()
if connerr != nil {
dbconf := dbConnection.DbConf
dbConnection.Connt(&dbconf)
log.Printf("Mysql连接不可用 <%v>", connerr)
}
q.DB = dbConnection.DB
q.Prefix = dbConnection.DbPrefix
}
func (q *DbQuery) Table(table string) *DbQuery {
var b strings.Builder
b.WriteString(q.Prefix)
b.WriteString(table)
q.table = b.String()
return q
}
func (q *DbQuery) Alias(alias string) *DbQuery {
q.alias = alias
return q
}
func (q *DbQuery) In(in string, v []interface{}) *DbQuery {
l := len(v)
if l > 0 {
q.in = v
var b strings.Builder
b.WriteString(in)
b.WriteString(" IN (")
for k, _ := range v {
b.WriteString("?")
if k < (l - 1) {
b.WriteString(",")
}
}
b.WriteString(") ")
if q.Wher != "" {
q.Wher += " AND " + b.String()
q.args = append(q.args, v...)
} else {
q.Wher = " WHERE " + b.String()
q.args = v
}
}
return q
}
func (q *DbQuery) OrIn(in string, v []interface{}) *DbQuery {
l := len(v)
if l > 0 {
q.in = v
var b strings.Builder
b.WriteString(in)
b.WriteString(" IN (")
for k, _ := range v {
b.WriteString("?")
if k < (l - 1) {
b.WriteString(",")
}
}
b.WriteString(") ")
if q.Wher != "" {
q.Wher += " OR " + b.String()
q.args = append(q.args, v...)
} else {
q.Wher = " WHERE " + b.String()
q.args = v
}
}
return q
}
func (q *DbQuery) Where(wher string, v interface{}) *DbQuery {
if wher != "" {
if q.Wher != "" {
q.Wher += " AND " + wher
q.args = append(q.args, v)
} else {
q.Wher = " WHERE " + wher
q.args = append(q.args, v)
}
}
return q
}
func (q *DbQuery) Or(or string, v interface{}) *DbQuery {
if or != "" {
if q.Wher != "" {
q.Wher += " OR " + or
q.args = append(q.args, v)
} else {
q.Wher = " Where " + or
q.args = append(q.args, v)
}
}
return q
}
func (q *DbQuery) Order(order string) *DbQuery {
if order != "" {
q.order = " ORDER BY " + order
}
return q
}
//涉及线程安全,改用字符串
func (q *DbQuery) Join(jType string, table string, on string) *DbQuery {
join := ""
if q.Joinn != "" {
join = q.Joinn
}
var b strings.Builder
b.WriteString(join)
joinStr := ""
switch jType {
case "left":
joinStr = " LEFT JOIN "
case "right":
joinStr = " RIGHT JOIN "
case "inner":
joinStr = " INNER JOIN "
}
b.WriteString(joinStr)
b.WriteString(q.Prefix)
b.WriteString(table)
b.WriteString(" ON ")
b.WriteString(on)
b.WriteString(" ")
q.Joinn = b.String()
return q
}
func (q *DbQuery) Count() int {
q.Field("count(*) as count")
query := q.SelectSql()
log.Println(query, q.args)
rows, err := q.DB.Query(query, q.args...)
if err != nil {
log.Println("Query error", err)
}
ret := q.GetRow(rows)["count"]
switch ret.(type) {
case int64:
return int(ret.(int64))
case string:
res, _ := strconv.Atoi(ret.(string))
return res
}
return 0
}
func (q *DbQuery) Field(field string) *DbQuery {
if field != "" {
q.field = field
}
return q
}
func (q *DbQuery) SelectSql() string {
var b strings.Builder
b.WriteString("SELECT ")
b.WriteString(q.field)
b.WriteString(" FROM ")
b.WriteString(q.table)
b.WriteString(" ")
b.WriteString(q.alias)
b.WriteString(" ")
b.WriteString(q.Joinn)
b.WriteString(" ")
b.WriteString(q.Wher)
b.WriteString(" ")
b.WriteString(q.group)
b.WriteString(" ")
b.WriteString(q.having)
b.WriteString(" ")
b.WriteString(q.order)
b.WriteString(" ")
b.WriteString(q.limit)
return b.String()
}
func (q *DbQuery) Query(sql string, args ...interface{}) ([]map[string]interface{}, error) {
log.Println(sql, args)
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
if e != nil {
conn.Close()
log.Println("Query error", e)
return nil, e
}
rows, err := conn.QueryContext(ctx, sql, args...)
if err != nil {
conn.Close()
log.Println("Query error", err)
return nil, err
}
defer func() {
conn.Close()
}()
return q.GetRows(rows), nil
}
func (q *DbQuery) Exec(sql string, args ...interface{}) (sql.Result, error) {
log.Println(sql, args)
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
if e != nil {
conn.Close()
log.Println("Query error", e)
return nil, e
}
res, err := conn.ExecContext(ctx, sql, args...)
if err != nil {
conn.Close()
log.Println("Query error", err)
return nil, err
}
defer func() {
conn.Close()
}()
return res, nil
}
func (q *DbQuery) Select() ([]map[string]interface{}, error) {
query := q.SelectSql()
log.Println(query, q.args)
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
if e != nil {
conn.Close()
log.Println("Query error", e)
return nil, e
}
rows, err := conn.QueryContext(ctx, query, q.args...)
if err != nil {
conn.Close()
log.Println("Query error", err)
return nil, err
}
defer func() {
conn.Close()
}()
return q.GetRows(rows), nil
}
func (q *DbQuery) Find() (map[string]interface{}, error) {
query := q.SelectSql()
log.Println(query, q.args)
//使用DB查询
var build strings.Builder
build.WriteString(query)
build.WriteString(" LIMIT 1")
rows, err := q.DB.Query(build.String(), q.args...)
if err != nil {
log.Println("Query error", err)
return nil, err
}
return q.GetRow(rows), nil
}
func (q *DbQuery) Update(update map[string]interface{}) (sql.Result, error) {
defer func() {
if err := recover(); err != nil {
stack := debug.Stack()
log.Println(err, string(stack))
}
}()
query, value := buileUpdateParams(q, update, q.args...)
if query == "" {
return nil, nil
}
fmt.Println(query, update, value, q.args)
ctx, cancel := context.WithCancel(context.Background())
conn, e := q.DB.Conn(ctx)
if e != nil {
conn.Close()
cancel()
log.Println("Query error", e)
return nil, e
}
res, err := conn.ExecContext(ctx, query, value...)
if err != nil {
conn.Close()
cancel()
log.Println("Query error", err)
return nil, err
}
defer func() {
conn.Close()
cancel()
}()
return res, nil
}
func (q *DbQuery) Save(save map[string]interface{}) (sql.Result, error) {
query, value := buileSaveParams(q, save)
if query == "" {
return nil, nil
}
log.Println(query, save)
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
if e != nil {
log.Println("Query error", e)
return nil, e
}
res, err := conn.ExecContext(ctx, query, value...)
if err != nil {
conn.Close()
log.Println("Query error", err)
return nil, err
}
conn.Close()
return res, nil
}
func buileUpdateParams(q *DbQuery, update map[string]interface{}, where ...interface{}) (string, []interface{}) {
into := ""
var value []interface{}
var binto strings.Builder
var b strings.Builder
if update != nil {
i := len(update)
for key := range update {
i--
binto.WriteString(key)
binto.WriteString(" = ?")
if len(update) > 0 && i > 0 {
binto.WriteString(",")
}
value = append(value, update[key])
}
into = binto.String()
b.WriteString("UPDATE ")
b.WriteString(q.table)
b.WriteString(" SET ")
b.WriteString(into)
b.WriteString(" ")
b.WriteString(q.Wher)
}
if len(where) > 0 {
for _, v := range where {
value = append(value, v)
}
}
query := b.String()
return query, value
}
func buileSaveParams(q *DbQuery, save map[string]interface{}) (string, []interface{}) {
query, into := "", ""
var value []interface{}
var buildPlace strings.Builder
var buildInto strings.Builder
var b strings.Builder
if save != nil {
buildInto.WriteString(" (")
buildPlace.WriteString(")VALUES( ")
i := len(save)
for key := range save {
i--
buildInto.WriteString(key)
buildPlace.WriteString("?")
if len(save) > 0 && i > 0 {
buildInto.WriteString(",")
buildPlace.WriteString(",")
}
value = append(value, save[key])
}
place := buildPlace.String()
into = buildInto.String()
b.WriteString("INSERT INTO ")
b.WriteString(q.table)
b.WriteString(into)
b.WriteString(place)
b.WriteString(")")
query = b.String()
return query, value
} else {
return query, nil
}
}
//删除
func buileDeleteParams(q *DbQuery) string {
var b strings.Builder
b.WriteString("DELETE FROM ")
b.WriteString(q.table)
b.WriteString(" ")
b.WriteString(q.Wher)
query := b.String()
return query
}
//创建事务
func (q *DbQuery) CreateDBTx() (context.Context, *sql.Tx, error) {
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
if e == nil {
opts := new(sql.TxOptions)
tx, err := conn.BeginTx(ctx, opts)
if err == nil {
return ctx, tx, err
} else {
return nil, nil, err
}
}
log.Println("===创建事务失败:===", e)
return nil, nil, e
}
//事务写入
func (q *DbQuery) TxSave(ctx context.Context, tx *sql.Tx, save map[string]interface{}) (sql.Result, error) {
query, value := buileSaveParams(q, save)
if query == "" {
return nil, nil
}
log.Println(query, value)
var result sql.Result
res, err := tx.ExecContext(ctx, query, value...)
if err != nil {
log.Println("Query error", err)
e := tx.Rollback()
if e != nil {
log.Println("Query error", e)
}
}
result = res
return result, err
}
//事务更新
func (q *DbQuery) TxUpdate(ctx context.Context, tx *sql.Tx, update map[string]interface{}, where ...interface{}) (sql.Result, error) {
query, value := buileUpdateParams(q, update, where...)
if query == "" {
return nil, nil
}
log.Println(query, value)
var result sql.Result
res, err := tx.ExecContext(ctx, query, value...)
if err != nil {
log.Println("Query error", err)
e := tx.Rollback()
if e != nil {
log.Println("Query error", e)
}
}
result = res
return result, err
}
func (q *DbQuery) Del() sql.Result {
query := buileDeleteParams(q)
if query == "" {
return nil
}
log.Println(query, q.args)
ctx := context.Background()
conn, e := q.DB.Conn(ctx)
var result sql.Result
if e == nil {
res, err := conn.ExecContext(ctx, query, q.args...)
if err != nil {
log.Println("Query error", err)
}
result = res
conn.Close()
} else {
log.Println("Query error", e)
}
conn.Close()
return result
}
func (q *DbQuery) Limit(limit string) *DbQuery {
if limit != "" {
q.limit = " LIMIT " + limit + ""
}
return q
}
func (q *DbQuery) Size(page int, size int) *DbQuery {
start := (page - 1) * size
startToStr := strconv.Itoa(start)
sizeToStr := strconv.Itoa(size)
var b strings.Builder
b.WriteString(" LIMIT ")
b.WriteString(startToStr)
b.WriteString(",")
b.WriteString(sizeToStr)
limitStr := b.String()
q.limit = limitStr
return q
}
func (q *DbQuery) Group(group string) *DbQuery {
if group != "" {
q.group = " GROUP BY " + group
}
return q
}
func (q *DbQuery) Having(h string, v interface{}) *DbQuery {
if h != "" {
q.having = " HAVING " + h
q.args = append(q.args, v)
}
return q
}
func (q *DbQuery) GetRows(query *sql.Rows) []map[string]interface{} {
defer func() {
query.Close()
}()
columns, _ := query.Columns()
field := make([]interface{}, len(columns))
//让每一行数据都填充到[][]byte里面
for i := range field {
var v interface{}
field[i] = &v
}
var results []map[string]interface{}
for query.Next() {
if err := query.Scan(field...); err != nil {
fmt.Println(err)
}
row := make(map[string]interface{})
for k, val := range field {
v := *(val.(*interface{}))
key := columns[k]
row[key] = assertion(v)
}
results = append(results, row)
}
return results
}
func (q *DbQuery) GetRow(query *sql.Rows) map[string]interface{} {
defer func() {
query.Close()
}()
columns, _ := query.Columns()
field := make([]interface{}, len(columns))
for i := range field {
var v interface{}
field[i] = &v
}
row := map[string]interface{}{}
for query.Next() {
if err := query.Scan(field...); err != nil {
fmt.Println(err)
}
for k, val := range field {
v := *(val.(*interface{}))
key := columns[k]
row[key] = assertion(v)
}
break
}
return row
}
func assertion(v interface{}) interface{} {
var t interface{}
switch v.(type) {
case int64:
t = int64(v.(int64))
case int32:
t = int32(v.(int32))
case int16:
t = int16(v.(int16))
case int8:
t = int8(v.(int8))
case int:
t = int(v.(int))
case []uint8:
t = string(v.([]uint8))
case float32:
t = float32(v.(float32))
case float64:
t = float64(v.(float64))
case uint8:
t = uint8(v.(uint8))
case uint16:
t = uint16(v.(uint16))
case uint32:
t = uint32(v.(uint32))
case uint64:
t = uint64(v.(uint64))
case nil:
t = nil
default:
t = v
}
return t
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/simon_git_code/gomysql.git
git@gitee.com:simon_git_code/gomysql.git
simon_git_code
gomysql
gomysql
v1.0.2

搜索帮助