Browse Source

腾讯云mariadb查询方法

master v0.1.0
guzeng 2 years ago
parent
commit
26ad8c68f6
13 changed files with 3112 additions and 0 deletions
  1. +32
    -0
      tencentdb/README.md
  2. +502
    -0
      tencentdb/chain.go
  3. +21
    -0
      tencentdb/chain_test.go
  4. +187
    -0
      tencentdb/conn.go
  5. +905
    -0
      tencentdb/db.go
  6. +51
    -0
      tencentdb/db_test.go
  7. +7
    -0
      tencentdb/go.mod
  8. +11
    -0
      tencentdb/go.sum
  9. +456
    -0
      tencentdb/prepare.go
  10. +21
    -0
      tencentdb/prepare_test.go
  11. +167
    -0
      tencentdb/string.go
  12. +301
    -0
      tencentdb/transaction.go
  13. +451
    -0
      tencentdb/transaction_chain.go

+ 32
- 0
tencentdb/README.md View File

@ -0,0 +1,32 @@
# dbquery
腾讯云mariadb一主多从数据库操作
## 链式查询使用
```
查询单条记录
map,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").Value(1).Value("test").Find()
查询列表
list,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").Value(1).Value("test").Select()
条件"或"
list,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").WhereOr("mobile=?").Value(1).Value("test").Value("22").Select()
联表查
使用Join
list,err := new(Query).Db(dbname).Table(tablename).Join([]string{jointable,tablename.id=jointable.cid,"LEFT"}).Where("id=?").Where("name=?").Value(1).Value("test").Select()
更新
ret,err := new(Query).Db(dbname).Table(tablename).Data("name=?").Data("depart=?").Value("xxx").Value("test").Update()
插入
ret,err := new(Query).Db(dbname).Table(tablename).Data("name=?").Data("depart=?").Value("xxx").Value("test").Create()
删除
ret,err := new(Query).Db(dbname).Table(tablename).Where("name=?").Where("depart=?").Value("xxx").Value("test").Delete()
```

+ 502
- 0
tencentdb/chain.go View File

@ -0,0 +1,502 @@
package tencentdb
import (
"database/sql"
"errors"
"log"
"strconv"
"strings"
)
var stmt *sql.Stmt
var err error
type Query struct {
dbname string
table string
alias string
title string
where []string
where_or []string
join [][]string //[["tablea as a","a.id=b.id","left"]]
data []string
value []interface{}
orderby string
page int
page_size int
stmt *sql.Stmt
conn *sql.DB
debug bool
dbtype string
}
func NewQuery(t ...string) *Query {
return &Query{
conn: DB,
dbtype: "mysql",
}
}
func (this *Query) Conn(conn *sql.DB) *Query {
this.conn = conn
return this
}
func (this *Query) ConnClose() error {
return this.conn.Close()
}
func (this *Query) Db(dbname string) *Query {
this.dbname = dbname
return this
}
func (this *Query) Table(tablename string) *Query {
this.table = tablename
return this
}
func (this *Query) Alias(tablename string) *Query {
this.alias = tablename
return this
}
func (this *Query) Title(title string) *Query {
this.title = title
return this
}
func (this *Query) Page(page int) *Query {
this.page = page
return this
}
func (this *Query) PageSize(page_num int) *Query {
this.page_size = page_num
return this
}
func (this *Query) Orderby(orderby string) *Query {
this.orderby = orderby
return this
}
func (this *Query) Where(where string) *Query {
this.where = append(this.where, where)
return this
}
func (this *Query) Wheres(wheres []string) *Query {
if len(wheres) > 0 {
this.where = append(this.where, wheres...)
}
return this
}
func (this *Query) WhereOr(where string) *Query {
this.where_or = append(this.where_or, where)
return this
}
func (this *Query) Value(value interface{}) *Query {
this.value = append(this.value, value)
return this
}
func (this *Query) Values(values []interface{}) *Query {
this.value = append(this.value, values...)
return this
}
func (this *Query) Join(join []string) *Query {
this.join = append(this.join, join)
return this
}
func (this *Query) Data(data string) *Query {
this.data = append(this.data, data)
return this
}
func (this *Query) Datas(datas []string) *Query {
this.data = append(this.data, datas...)
return this
}
func (this *Query) Debug(debug bool) *Query {
this.debug = debug
return this
}
/*
* 清理上次查询
*/
func (this *Query) Clean() *Query {
this.title = ""
this.where = this.where[0:0]
this.where_or = this.where_or[0:0]
this.join = this.join[0:0]
this.data = this.data[0:0]
this.value = this.value[0:0]
this.orderby = ""
this.page = 0
this.page_size = 0
return this
}
// 拼查询sql
func (this *Query) QueryStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
table := getTableName(this.dbname, this.table, this.dbtype)
// var err error
var sql, title string
if this.title != "" {
title = this.title
} else {
title = "*"
}
sql = StringJoin("/*slave*/ select ", title)
if this.alias != "" {
table = StringJoin(table, " as ", this.alias)
}
sql = StringJoin(sql, " from ", table)
if len(this.join) > 0 {
for _, joinitem := range this.join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql = StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0], this.dbtype), " on ", joinitem[1])
} else { //默认左连接
sql = StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0], this.dbtype), " on ", joinitem[1])
}
}
}
if len(this.where) > 0 || len(this.where_or) > 0 {
sql = StringJoin(sql, " where ")
}
if len(this.where) > 0 {
sql = StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ")
}
if len(this.where_or) > 0 {
if len(this.where) > 0 {
sql = StringJoin(sql, " or ", strings.Join(this.where_or, " or "))
} else {
sql = StringJoin(sql, strings.Join(this.where_or, " or "))
}
}
if this.orderby != "" {
sql = StringJoin(sql, " order by ", this.orderby)
}
if this.page > 0 || this.page_size > 0 {
if this.page < 1 {
this.page = 1
}
if this.page_size < 1 {
this.page_size = 10
}
from := strconv.Itoa((this.page - 1) * this.page_size)
offset := strconv.Itoa(this.page_size)
if from != "" && offset != "" {
sql = StringJoin(sql, " limit ", from, " , ", offset)
}
}
if this.debug {
log.Println("query sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼更新sql
func (this *Query) UpdateStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
if len(this.where) < 1 {
return errors.New("参数错误,缺少条件")
}
dbName := getTableName(this.dbname, this.table, this.dbtype)
var sql string
sql = StringJoin("update ", dbName, " set ", strings.Join(this.data, " , "))
sql = StringJoin(sql, " where ", strings.Join(this.where, " and "))
if this.debug {
log.Println("update sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼插入sql
func (this *Query) CreateStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
dbName := getTableName(this.dbname, this.table, this.dbtype)
var sql string
sql = StringJoin("insert into ", dbName, " set ", strings.Join(this.data, " , "))
if this.debug {
log.Println("insert sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼删除sql
func (this *Query) DeleteStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
if len(this.where) < 1 {
return errors.New("参数错误,缺少条件")
}
dbName := getTableName(this.dbname, this.table, this.dbtype)
var sql string
sql = StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and "))
if this.page_size > 0 {
sql = StringJoin(sql, " limit ", strconv.Itoa(this.page_size))
}
if this.debug {
log.Println("delete sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
/**
* 执行查询列表
* return list error
*/
func (this *Query) Select() ([]map[string]string, error) {
conn, err := connectDb(dbhost_slaver, dbuser_slaver, dbpwd_slaver, dbname_slaver, dbport_slaver, 1, 0)
if err != nil {
log.Println("new query error:", err)
}
if conn == nil {
log.Println("Err: no conn")
}
_, rows, err := FetchRows(conn, this.dbname, this.table, this.alias, this.title, this.join,
this.where, this.where_or, this.value, this.orderby, this.page, this.page_size, this.debug)
conn.Close()
return rows, err
}
/**
* 执行查询多条数据
* return row error
* 2022/01/05
*/
func (this *Query) List() ([]map[string]string, error) {
err := this.QueryStmt()
if err != nil {
return []map[string]string{}, err
}
if this.stmt == nil {
return []map[string]string{}, errors.New("缺少必要参数")
}
list, err := StmtForQueryList(this.stmt, this.value)
return list, err
}
/**
* 执行查询一条数据
* return row error
*/
func (this *Query) Find() (map[string]string, error) {
conn, err := connectDb(dbhost_slaver, dbuser_slaver, dbpwd_slaver, dbname_slaver, dbport_slaver, 1, 0)
if err != nil {
log.Println("new query error:", err)
}
if conn == nil {
log.Println("Err: no conn")
}
_, row, err := GetRow(conn, this.dbname, this.table, this.alias, this.title, this.join,
this.where, this.where_or, this.value, this.orderby, this.debug)
conn.Close()
return row, err
}
/**
* 执行查询一条数据
* return row error
* 2022/01/05
*/
func (this *Query) Get() (map[string]string, error) {
this.page = 1
this.page_size = 1
err := this.QueryStmt()
if err != nil {
return map[string]string{}, err
}
if this.stmt == nil {
return nil, errors.New("缺少必要参数")
}
row, err := StmtForQueryRow(this.stmt, this.value)
return row, err
}
/**
* 执行更新
* return is_updated error
*/
func (this *Query) Update() (int64, error) {
err := this.UpdateStmt()
if err != nil {
return 0, err
}
ret, err := StmtForUpdateExec(this.stmt, this.value)
return ret, err
}
/**
* 执行删除
* return is_delete error
*/
func (this *Query) Delete() (int64, error) {
err := this.DeleteStmt()
if err != nil {
return 0, err
}
ret, err := StmtForUpdateExec(this.stmt, this.value)
return ret, err
}
/**
* 执行写入
* return is_insert error
*/
func (this *Query) Create() (int64, error) {
err := this.CreateStmt()
if err != nil {
return 0, err
}
ret, err := StmtForInsertExec(this.stmt, this.value)
return ret, err
}

+ 21
- 0
tencentdb/chain_test.go View File

@ -0,0 +1,21 @@
package tencentdb
import (
"testing"
)
func Test_Chain(t *testing.T) {
ConnectSlaver("106.52.13.101", "yueheng_slaver", "yhslave^%*345Sr", "shop_test", "13306")
for i := 0; i < 10000; i++ {
t.Log("i:", i)
ret, err := NewQuery().Db("shop_test").Table("ttl_order_product").Alias("op").
Join([]string{"ttl_product as p", "op.product_id=p.id"}).
Title("op.id,op.order_price,p.thumb").WhereOr("op.id =?").WhereOr("op.id = ?").Value(63).Value(64).Debug(true).Select()
t.Log(len(ret))
// t.Log(ret)
t.Log(err)
}
}

+ 187
- 0
tencentdb/conn.go View File

@ -0,0 +1,187 @@
package tencentdb
import (
"database/sql"
"log"
"errors"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
)
var DB *sql.DB
var dbhost_slaver, dbname_slaver, dbport_slaver, dbuser_slaver, dbpwd_slaver string //从库信息
var use_slaver bool = false
func Connect(DBHOST, DBUSER, DBPWD, DBNAME, DBPORT string, conns ...int) error {
log.Println("database connectting...")
var dbConnErr error
if DBHOST != "" && DBUSER != "" && DBPWD != "" && DBPORT != "" { //&& DBNAME != ""
for i := 0; i < 10; i++ {
DB, dbConnErr = sql.Open("mysql", DBUSER+":"+DBPWD+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8mb4")
if dbConnErr != nil {
log.Println("ERROR", "can not connect to Database, ", dbConnErr)
time.Sleep(time.Second * 5)
} else {
if len(conns) > 0 {
DB.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制
} else {
DB.SetMaxOpenConns(200) //默认值为0表示不限制
}
if len(conns) > 1 {
DB.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数
} else {
DB.SetMaxIdleConns(50)
}
DB.Ping()
log.Println("database connected")
DB.SetConnMaxLifetime(time.Minute * 2)
break
}
}
} else {
return errors.New("db connection params errors")
}
return dbConnErr
}
func CloseConn() error {
return DB.Close()
}
func ConnectSlaver(DBHOST, DBUSER_SLAVER, DBPWD_SLAVER, DBNAME, DBPORT string, conns ...int) {
dbhost_slaver = DBHOST
dbuser_slaver = DBUSER_SLAVER
dbpwd_slaver = DBPWD_SLAVER
dbname_slaver = DBNAME
dbport_slaver = DBPORT
use_slaver = true
// log.Println("database connectting with slaver...")
// var dbConnErr error
// if DBHOST != "" && DBUSER_SLAVER != "" && DBPWD_SLAVER != "" && DBPORT != "" { //&& DBNAME != ""
// for i := 0; i < 10; i++ {
// SLAVER_DB, dbConnErr = sql.Open("mysql", DBUSER_SLAVER+":"+DBPWD_SLAVER+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8mb4")
// if dbConnErr != nil {
// log.Println("ERROR", "can not connect to Database, ", dbConnErr)
// time.Sleep(time.Second * 5)
// } else {
// if len(conns) > 0 {
// SLAVER_DB.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制
// } else {
// SLAVER_DB.SetMaxOpenConns(200) //默认值为0表示不限制
// }
// if len(conns) > 1 {
// SLAVER_DB.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数
// } else {
// SLAVER_DB.SetMaxIdleConns(50)
// }
// SLAVER_DB.Ping()
// log.Println("database connected")
// SLAVER_DB.SetConnMaxLifetime(time.Minute * 2)
// break
// }
// }
// } else {
// return errors.New("db connection params errors")
// }
// return dbConnErr
}
func connectDb(dbhost, dbuser, dbpwd, dbname, dbport string, conns ...int) (*sql.DB, error) {
log.Println("database connectting...")
var dbconn *sql.DB
var dbConnErr error
if dbhost != "" && dbuser != "" && dbpwd != "" && dbport != "" {
for i := 0; i < 10; i++ {
dbconn, dbConnErr = sql.Open("mysql", dbuser+":"+dbpwd+"@tcp("+dbhost+":"+dbport+")/"+dbname+"?charset=utf8mb4")
if dbConnErr != nil {
log.Println("ERROR", "can not connect to Database, ", dbConnErr)
time.Sleep(time.Second * 5)
} else {
if len(conns) > 0 {
dbconn.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制
} else {
dbconn.SetMaxOpenConns(200) //默认值为0表示不限制
}
if len(conns) > 1 {
dbconn.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数
} else {
dbconn.SetMaxIdleConns(50)
}
// dbconn.Ping()
// log.Println(dbconn.Stats())
log.Println("database connected")
dbconn.SetConnMaxLifetime(time.Minute * 1)
break
}
}
} else {
return nil, errors.New("db connection params errors")
}
return dbconn, dbConnErr
}
// func CloseSlaverConn() error {
// return SLAVER_DB.Close()
// }
/**
* 检测表名
*/
func getTableName(dbName, table string, dbtype ...string) string {
var db_type string = "mysql"
if len(dbtype) > 0 {
if dbtype[0] != "" {
db_type = dbtype[0]
}
}
var ret string
switch db_type {
case "mysql":
if strings.Contains(table, ".") {
ret = table
}
if dbName != "" {
ret = StringJoin(dbName, ".", table)
} else {
ret = table
}
case "mssql":
ret = StringJoin(dbName, ".", table)
}
return ret
}
func GetDbTableName(dbName, table string) string {
return getTableName(dbName, table)
}
func judg() []string {
return []string{"=", ">", "<", "!=", "<=", ">="}
}

+ 905
- 0
tencentdb/db.go View File

@ -0,0 +1,905 @@
package tencentdb
import (
"database/sql"
"log"
"strconv"
"errors"
"strings"
"time"
_ "github.com/go-sql-driver/mysql"
)
/**
* 创建数据
*/
func Insert(dbName, table string, data map[string]string) (int64, error) {
var insertId int64
var err error
if dbName == "" && table == "" {
return insertId, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if len(data) < 1 {
return insertId, errors.New("没有要写入的数据")
}
keyList := make([]string, len(data))
keyStr := make([]string, len(data))
valueList := make([]interface{}, len(data))
var i int = 0
for key, value := range data {
keyList[i] = key
keyStr[i] = "?"
valueList[i] = value
i++
}
result, err := DB.Exec("insert into "+dbName+" ("+strings.Join(keyList, ",")+") value("+strings.Join(keyStr, ",")+")", valueList...)
if err != nil {
log.Println("ERROR|插入", dbName, "数据失败,", err)
return insertId, err
} else {
insertId, _ = result.LastInsertId()
time.Sleep(time.Second * 2)
return insertId, nil
}
}
/**
* 修改数据
*/
func Update(dbName, table string, data map[string]string, where map[string]string) (int64, error) {
var rowsAffected int64
var err error
if dbName == "" && table == "" {
return rowsAffected, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if len(data) < 1 {
return rowsAffected, errors.New("同有更新的数据")
}
if len(where) < 1 {
return rowsAffected, errors.New("没有更新条件")
}
keyList := make([]string, len(data))
valueList := make([]interface{}, len(data), len(data)+len(where))
whereStr := make([]string, len(where))
var i int = 0
empty := false
for key, value := range data {
keyList[i] = key + "=?"
valueList[i] = value
i++
}
i = 0
for key, value := range where {
if value == "" {
empty = true
break
}
whereStr[i] = key + "=?"
valueList = append(valueList, value)
i++
}
if empty {
log.Println("ERROR|修改数据表", dbName, "时条件中有空数据,条件:", where, "数据:", data)
return rowsAffected, errors.New("条件中有空数据")
}
result, err := DB.Exec("update "+dbName+" set "+strings.Join(keyList, " , ")+" where "+strings.Join(whereStr, " and "), valueList...)
if err != nil {
log.Println("ERROR|修改", dbName, "数据失败,", err)
return rowsAffected, err
} else {
rowsAffected, _ = result.RowsAffected()
return rowsAffected, nil
}
}
/**
* 删除数据
* @param count 删除数量
*/
func Delete(dbName, table string, data map[string]string, del_count ...string) (int64, error) {
var count int64
var err error
if dbName == "" && table == "" {
return count, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if len(data) < 1 {
return count, errors.New("没有要删除的数据")
}
keyList := make([]string, len(data))
valueList := make([]interface{}, len(data))
var i int = 0
empty := false
for key, value := range data {
if value == "" {
empty = true
break
}
keyList[i] = key + "=?"
valueList[i] = value
i++
}
if empty {
log.Println("ERROR|删除数据表", dbName, "时条件中有空数据,条件:", data)
return count, errors.New("条件中有空数据")
}
var limitStr string = ""
if len(del_count) > 0 {
limitStr = " limit " + del_count[0]
}
result, err := DB.Exec("delete from "+dbName+" where "+strings.Join(keyList, " and ")+limitStr, valueList...)
if err != nil {
log.Println("ERROR|删除", dbName, "数据失败,", err)
return count, err
} else {
count, _ = result.RowsAffected()
return count, nil
}
}
/**
* 查找一条记录
* @param dbName 数据表名
* @param title 查询字段名
*/
func GetData(dbName, table string, title string, where map[string]string, limit map[string]string) (int, map[string]string, error) {
var count int = 0
info := make(map[string]string)
if dbName == "" && table == "" {
return count, info, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if len(title) < 1 {
return count, info, errors.New("没有指定查询内容")
}
var limitStr string = ""
if limit != nil && len(limit) > 0 {
var from string = "0" //开始
if _, ok := limit["order"]; ok {
limitStr += " order by " + limit["order"]
}
if _, ok := limit["from"]; ok {
from = limit["from"]
}
limitStr += " limit " + from + ",1"
} else {
limitStr = " limit 1"
}
if len(where) < 1 {
return count, info, errors.New("Query condition is empty")
}
keyList := make([]string, len(where))
valueList := make([]interface{}, len(where))
var i int = 0
empty := false
for key, value := range where {
if value == "" {
empty = true
break
}
keyList[i] = key + " = ? "
valueList[i] = value
i++
}
if empty {
return count, info, errors.New("Query condition is empty")
}
var rows *sql.Rows
var err error
var queryNum int = 0
for queryNum < 3 { //如发生错误,继续查询3次,防止数据库连接断开问题
rows, err = DB.Query("SELECT "+title+" FROM "+dbName+" where "+strings.Join(keyList, " and ")+" "+limitStr, valueList...)
if err == nil {
break
} else {
log.Println("ERROR", "Query from", dbName, "failed,", err, "| SELECT "+title+" FROM "+dbName+" where "+strings.Join(keyList, " and ")+" "+limitStr)
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
defer rows.Close()
if err != nil {
return count, info, err
}
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var index string
var rowerr error
for rows.Next() {
rowerr = rows.Scan(scanArgs...)
if rowerr == nil {
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
info[index] = ToString(col)
}
}
count++
} else {
log.Println("ERROR", "rows scan error", rowerr, dbName, keyList, valueList)
}
}
if rowerr != nil {
return count, info, rowerr
}
return count, info, nil
}
/**
* 查找一条记录
* @param dbName 数据表名
* @param title 查询字段名
*/
func GetRow(dbconn *sql.DB, dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby string, debug bool) (int, map[string]string, error) {
var count int = 0
info := make(map[string]string)
if dbName == "" && table_name == "" {
return count, info, errors.New("没有数据表")
}
table := getTableName(dbName, table_name)
var sql_str, title string
if titles != "" {
title = titles
} else {
title = "*"
}
sql_str = StringJoin("/*slave*/ select ", title)
if alias != "" {
table = StringJoin(table, " as ", alias)
}
sql_str = StringJoin(sql_str, " from ", table)
if len(join) > 0 {
for _, joinitem := range join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql_str = StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql_str = StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(where) > 0 || len(where_or) > 0 {
sql_str = StringJoin(sql_str, " where ")
}
if len(where) > 0 {
sql_str = StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ")
}
if len(where_or) > 0 {
if len(where) > 0 {
sql_str = StringJoin(sql_str, " or ", strings.Join(where_or, " or "))
} else {
sql_str = StringJoin(sql_str, strings.Join(where_or, " or "))
}
}
if orderby != "" {
sql_str = StringJoin(sql_str, " order by ", orderby)
}
if debug {
log.Println("query sql:", sql_str, valueList)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql_str {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(valueList) {
return 0, nil, errors.New("参数错误,条件值错误")
}
var rows *sql.Rows
var err error
var queryNum int = 0
sql_str = StringJoin(sql_str, " limit 1")
for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题
rows, err = dbconn.Query(sql_str, valueList...)
if err == nil {
break
} else {
log.Println(err)
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
if err != nil {
rows.Close()
return count, info, err
}
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var index string
var rowerr error
for rows.Next() {
rowerr = rows.Scan(scanArgs...)
if rowerr == nil {
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
info[index] = ToString(col)
}
}
count++
} else {
log.Println("ERROR", rowerr)
}
}
rows.Close()
if rowerr != nil {
return count, info, rowerr
}
return count, info, nil
}
/**
* 查找多条记录
* @param dbName 数据表名
* @param title 查询字段名
*/
func FetchRows(dbconn *sql.DB, dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby string, page int, page_size int, debug bool) (int, []map[string]string, error) {
var count int = 0
list := make([]map[string]string, 0)
if dbName == "" && table_name == "" {
return count, list, errors.New("没有数据表")
}
table := getTableName(dbName, table_name)
var sql_str, title string
if titles != "" {
title = titles
} else {
title = "*"
}
sql_str = StringJoin("/*slave*/ select ", title)
if alias != "" {
table = StringJoin(table, " as ", alias)
}
sql_str = StringJoin(sql_str, " from ", table)
if len(join) > 0 {
for _, joinitem := range join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql_str = StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql_str = StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(where) > 0 || len(where_or) > 0 {
sql_str = StringJoin(sql_str, " where ")
}
if len(where) > 0 {
sql_str = StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ")
}
if len(where_or) > 0 {
if len(where) > 0 {
sql_str = StringJoin(sql_str, " or ", strings.Join(where_or, " or "))
} else {
sql_str = StringJoin(sql_str, strings.Join(where_or, " or "))
}
}
if orderby != "" {
sql_str = StringJoin(sql_str, " order by ", orderby)
}
if page > 0 || page_size > 0 {
if page < 1 {
page = 1
}
if page_size < 1 {
page_size = 10
}
from := strconv.Itoa((page - 1) * page_size)
offset := strconv.Itoa(page_size)
if from != "" && offset != "" {
sql_str = StringJoin(sql_str, " limit ", from, " , ", offset)
}
}
if debug {
log.Println("query sql:", sql_str, valueList)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql_str {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(valueList) {
return 0, list, errors.New("参数错误,条件值错误")
}
var rows *sql.Rows
var err error
var queryNum int = 0
for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题
rows, err = dbconn.Query(sql_str, valueList...)
if err == nil {
break
} else {
log.Println(err)
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
if err != nil {
rows.Close()
return 0, list, err
}
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var index string
var rowerr error
var info map[string]string
for rows.Next() {
rowerr = rows.Scan(scanArgs...)
info = make(map[string]string)
if rowerr == nil {
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
info[index] = ToString(col)
}
}
count++
} else {
log.Println("ERROR", rowerr)
}
if len(info) > 0 {
list = append(list, info)
}
}
rows.Close()
return count, list, nil
}
func GetInfo(dbName, table string, title string, where map[string]string) (map[string]string, error) {
count, info, gzErr := GetData(dbName, table, title, where, nil)
if gzErr != nil {
return info, gzErr
} else {
if count < 1 {
return info, errors.New("No data")
}
return info, nil
}
}
/**
* 查询列表
* 2018/04/19
*/
func GetList(dbName, table string, title string, where map[string]string, limit map[string]string) ([]map[string]string, error) {
var list []map[string]string
if dbName == "" && table == "" {
return list, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
var rows *sql.Rows
var err error
var queryNum int = 0
var limitStr string = ""
if len(limit) > 0 {
var offset string = "0" //偏移量,个数
var from string = "" //开始
if _, ok := limit["order"]; ok {
limitStr += " order by " + limit["order"]
}
if _, ok := limit["offset"]; ok {
offset = limit["offset"]
}
if _, ok := limit["from"]; ok {
from = limit["from"]
}
if offset != "0" && from != "" {
limitStr += " limit " + from + "," + offset
}
}
if len(where) > 0 {
valueList := make([]interface{}, len(where))
whereStr := make([]string, len(where))
i := 0
var keys []string
for key, value := range where {
key = strings.Trim(key, " ")
value = strings.Trim(value, " ")
if value == "" || key == "" {
continue
// return list, errors.New("Query condition is empty")
}
if strings.Contains(key, " ") {
//key中包含空格,判断是否不等于条件
keys = strings.Split(key, " ")
if IsInStringArray(judg(), strings.Trim(keys[1], " ")) {
whereStr[i] = strings.Trim(keys[0], " ") + " " + strings.Trim(keys[1], " ") + " ?"
}
} else {
whereStr[i] = key + " = ?"
valueList[i] = value
}
i++
}
if len(whereStr) == 0 || len(valueList) == 0 {
return list, errors.New("Query condition is empty")
}
for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题
rows, err = DB.Query("select "+title+" from "+dbName+" where "+strings.Join(whereStr, " and ")+" "+limitStr, valueList...)
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
} else {
for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题
rows, err = DB.Query("select " + title + " from " + dbName + " " + limitStr)
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
}
if err != nil {
return list, err
}
defer rows.Close()
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var record map[string]string
var index string
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(scanArgs...)
record = make(map[string]string)
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
record[index] = ToString(col)
}
}
list = append(list, record)
}
return list, nil
}
/**
* 查询总数
* 2018/04/19
*/
func GetTotal(dbName, table string, args ...string) (total int) {
if dbName == "" && table == "" {
return
}
dbName = getTableName(dbName, table)
var title string = "*"
if len(args) > 0 {
title = args[0]
}
var rows *sql.Rows
var err error
var queryNum int = 0
for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题
rows, err = DB.Query("select count(" + title + ") as count from " + dbName + " limit 1")
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
if err != nil {
log.Println("ERROR|get", dbName, "total error", err)
return
}
defer rows.Close()
var count int
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(&count)
if err != nil {
log.Println("ERROR|get", dbName, "total error", err)
} else {
total = count
}
}
return
}
/**
* 查询总数
* 2020/06/04
*/
func GetCount(dbName, table string, where map[string]string, args ...string) (total int) {
if dbName == "" && table == "" {
return
}
dbName = getTableName(dbName, table)
var title string = "*"
if len(title) > 0 {
title = args[0]
}
var rows *sql.Rows
var err error
var queryNum int = 0
if len(where) > 0 {
valueList := make([]interface{}, len(where))
whereStr := make([]string, len(where))
i := 0
var keys []string
for key, value := range where {
key = strings.Trim(key, " ")
value = strings.Trim(value, " ")
if value == "" || key == "" {
continue
// return list, errors.New("Query condition is empty")
}
if strings.Contains(key, " ") {
//key中包含空格,判断是否不等于条件
keys = strings.Split(key, " ")
if IsInStringArray(judg(), strings.Trim(keys[1], " ")) {
whereStr[i] = strings.Trim(keys[0], " ") + " " + strings.Trim(keys[1], " ") + " ?"
}
} else {
whereStr[i] = key + " = ?"
valueList[i] = value
}
i++
}
for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题
rows, err = DB.Query("select count("+title+") as count from "+dbName+" where "+strings.Join(whereStr, " and ")+" limit 1", valueList...)
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
} else {
for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题
rows, err = DB.Query("select count(" + title + ") as count from " + dbName + " limit 1")
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
}
if err != nil {
log.Println("ERROR|get", dbName, "count error", err)
return
}
defer rows.Close()
var count int
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(&count)
if err != nil {
log.Println("ERROR|get", dbName, "count error", err)
} else {
total = count
}
}
return
}
func DoQuery(args ...interface{}) ([]map[string]string, error) {
var list []map[string]string
if len(args) < 1 {
return list, errors.New("Query condition is empty")
}
queryStr := ToString(args[0])
if queryStr == "" {
return list, errors.New("Query condition is empty")
}
var rows *sql.Rows
var err error
var queryNum int = 0
for queryNum < 3 { //如发生错误,继续查询5次,防止数据库连接断开问题
if len(args) > 1 {
rows, err = DB.Query(queryStr, args[1:]...) //strings.Join(args[1:], ",")
if err != nil {
log.Println("ERROR|DoQuery error:", err)
}
} else {
rows, err = DB.Query(queryStr)
if err != nil {
log.Println("ERROR|DoQuery error:", err)
}
}
if err == nil {
break
} else {
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
if err != nil {
return list, err
}
defer rows.Close()
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var record map[string]string
var index string
for rows.Next() {
//将行数据保存到record字典
err = rows.Scan(scanArgs...)
record = make(map[string]string)
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
record[index] = ToString(col)
}
}
list = append(list, record)
}
return list, nil
}

+ 51
- 0
tencentdb/db_test.go View File

@ -0,0 +1,51 @@
package tencentdb
import (
"log"
"testing"
)
func Test_Connet(t *testing.T) {
//go func() {
for i := 0; i < 1; i++ {
dbhost := "localhost"
dbname := "shop"
dbusername := "tetele"
dbpassword := "fly123456"
dbport := "3306"
table := "ttl_order_product"
err := Connect(dbhost, dbusername, dbpassword, dbname, dbport)
if err != nil {
log.Println(err.Error())
}
//_,err = new(Query).Db(dbname).Table("ttl_user").Where("id > 0").Select()
// _, err = new(Query).Db(dbname).Table("ttl_news").
// Datas([]string{"title=?", "content=?"}).
// Values([]interface{}{"aaaaaaaaa", "bbbbbb"}).Create()
title := "op.id,op.sn,op.order_price"
alias := "op"
join := [][]string{}
join = append(join, []string{"ttl_product as p", "op.product_id=p.id"})
where := []string{}
where_or := []string{}
valueList := []interface{}{}
orderby := "id desc"
debug := true
// count, row, err := GetRow(dbname, table, alias, title, join, where, where_or, valueList, orderby, debug)
count, row, err := FetchRows(dbname, table, alias, title, join, where, where_or, valueList, orderby, 1, 10, debug)
log.Println(count)
log.Println(row)
log.Println(err)
if err != nil {
log.Println(err.Error())
}
}
//}()
}

+ 7
- 0
tencentdb/go.mod View File

@ -0,0 +1,7 @@
module git.tetele.net/mysql/tencentdb
go 1.16
require (
github.com/go-sql-driver/mysql v1.5.0
)

+ 11
- 0
tencentdb/go.sum View File

@ -0,0 +1,11 @@
git.tetele.net/tgo/helper v0.1.0 h1:ZdsBXUWX3+22ZzHTZRldBfBsQwu+CwUH8qScUvpgimE=
git.tetele.net/tgo/helper v0.1.0/go.mod h1:shYQE/hvMy3fOE8JXKGxvywOXiz3M5Nw4e+u7HR8+NY=
github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI=
github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs=
github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY=
github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI=
golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=

+ 456
- 0
tencentdb/prepare.go View File

@ -0,0 +1,456 @@
package tencentdb
import (
"database/sql"
"errors"
"log"
"strings"
)
/**
* 准备查询
* return Stmt error
*/
func StmtForRead(dbName, table string, title string, where []string, limit map[string]string) (*sql.Stmt, error) {
if dbName == "" && table == "" {
return nil, errors.New("参数错误,没有数据表")
}
dbName = getTableName(dbName, table)
if len(title) < 1 {
return nil, errors.New("没有要查询内容")
}
var limitStr string = ""
if limit != nil && len(limit) > 0 {
var from, offset string = "", "" //开始
if _, ok := limit["order"]; ok {
limitStr += " order by " + limit["order"]
}
if _, ok := limit["from"]; ok {
from = limit["from"]
}
if _, ok := limit["offset"]; ok {
offset = limit["offset"]
}
if from != "" && offset != "" {
limitStr += " limit " + from + "," + offset
}
}
var stmt *sql.Stmt
var err error
if len(where) > 0 {
// log.Println("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + limitStr)
stmt, err = DB.Prepare("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + limitStr)
} else {
// log.Println("SELECT " + title + " FROM " + dbName + limitStr)
stmt, err = DB.Prepare("SELECT " + title + " FROM " + dbName + limitStr)
}
return stmt, err
}
func CloseStmt(stmt *sql.Stmt) error {
return stmt.Close()
}
/**
* 执行查询列表
* return list error
*/
func StmtForQueryList(stmt *sql.Stmt, valuelist []interface{}) ([]map[string]string, error) {
if stmt == nil {
return nil, errors.New("缺少必要参数")
}
// log.Println(valuelist...)
rows, err := stmt.Query(valuelist...)
defer stmt.Close()
if err != nil {
if stmt != nil {
stmt.Close()
}
return nil, err
}
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var list []map[string]string
var index string
var rowerr error
info := make(map[string]string)
for rows.Next() {
rowerr = rows.Scan(scanArgs...)
info = make(map[string]string)
if rowerr == nil {
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
info[index] = ToString(col)
}
}
} else {
log.Println("rows scan error", rowerr)
}
if len(info) > 0 {
list = append(list, info)
}
}
return list, nil
}
/**
* 执行查询一条数据
* return row error
*/
func StmtForQueryRow(stmt *sql.Stmt, valuelist []interface{}) (map[string]string, error) {
if stmt == nil || len(valuelist) < 1 {
return nil, errors.New("缺少必要参数")
}
rows, err := stmt.Query(valuelist...)
defer stmt.Close()
if err != nil {
if stmt != nil {
stmt.Close()
}
return nil, err
}
columns, _ := rows.Columns()
scanArgs := make([]interface{}, len(columns))
values := make([]interface{}, len(columns))
for i := range values {
scanArgs[i] = &values[i]
}
var index string
var rowerr error
info := make(map[string]string)
for rows.Next() {
rowerr = rows.Scan(scanArgs...)
if rowerr == nil {
for i, col := range values {
if col != nil {
index = StrFirstToUpper(columns[i])
info[index] = ToString(col)
}
}
} else {
log.Println("rows scan error", rowerr)
}
}
if rowerr != nil {
return info, errors.New("数据出错")
}
return info, nil
}
/**
* 准备更新
* return Stmt error
*/
func StmtForUpdate(dbName, table string, data []string, where []string) (*sql.Stmt, error) {
if dbName == "" && table == "" {
return nil, errors.New("参数错误,没有数据表")
}
dbName = getTableName(dbName, table)
if len(where) < 1 {
return nil, errors.New("参数错误,没有更新条件")
}
var stmt *sql.Stmt
var err error
stmt, err = DB.Prepare("update " + dbName + " set " + strings.Join(data, " , ") + " where " + strings.Join(where, " and "))
return stmt, err
}
/**
* 执行更新
* return is_updated error
*/
func StmtForUpdateExec(stmt *sql.Stmt, valuelist []interface{}) (int64, error) {
res, err := stmt.Exec(valuelist...)
if err != nil {
return 0, errors.New("更新失败:" + err.Error())
}
return res.RowsAffected()
}
/**
* 准备写入
* return Stmt error
*/
func StmtForInsert(dbName, table string, data []string) (*sql.Stmt, error) {
if dbName == "" && table == "" {
return nil, errors.New("参数错误,没有数据表")
}
dbName = getTableName(dbName, table)
if len(data) < 1 {
return nil, errors.New("参数错误,没有要写入的数据")
}
var stmt *sql.Stmt
var err error
stmt, err = DB.Prepare("insert into " + dbName + " set " + strings.Join(data, " , "))
return stmt, err
}
/**
* 执行写入
* @return lastId error
*/
func StmtForInsertExec(stmt *sql.Stmt, valuelist []interface{}) (int64, error) {
res, err := stmt.Exec(valuelist...)
if err != nil {
return 0, errors.New("创建失败:" + err.Error())
}
return res.LastInsertId()
}
/**
* 使用db prepare方式查询列表
* @param dbName
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* @param page 查询范围可传两个值 pageNum,pageSize
* GZ
* 2020/05/19
*/
func GetListByStmt(dbName string, table string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) {
if len(page) > 0 {
pageNum, pageSize := page[0], 10
if len(page) > 1 {
pageSize = page[1]
}
limit["from"], limit["offset"] = GetPage(pageNum, pageSize)
}
stmt, err := StmtForRead(dbName, table, title, where, limit)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryList(stmt, valuelist)
}
/**
* 使用db prepare方式查询单条数据
* @param dbName
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* GZ
* 2020/05/19
*/
func GetDataByStmt(dbName string, table string, title string, where []string, valuelist []interface{}, limit map[string]string) (map[string]string, error) {
stmt, err := StmtForRead(dbName, table, title, where, limit)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryRow(stmt, valuelist)
}
/**
* 使用db prepare修改数据
* @param dbName
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* GZ
* 2020/05/19
*/
func UpdateByStmt(dbName string, table string, data []string, where []string, valuelist []interface{}) (int64, error) {
stmt, err := StmtForUpdate(dbName, table, data, where)
if err != nil {
return 0, err
}
defer stmt.Close()
return StmtForUpdateExec(stmt, valuelist)
}
/**
* 使用db prepare写入数据
* @param dbName
* @param table 表名
* @param data 写入的字段
* @param valuelist 写入的值
* GZ
* 2020/08/06
*/
func InsertByStmt(dbName string, table string, data []string, valuelist []interface{}) (int64, error) {
stmt, err := StmtForInsert(dbName, table, data)
if err != nil {
return 0, err
}
defer stmt.Close()
return StmtForInsertExec(stmt, valuelist)
}
/**
* 自定义查询
* return Stmt error
*/
func StmtForQuery(querysql string) (*sql.Stmt, error) {
if querysql == "" {
return nil, errors.New("参数错误,没有数据表")
}
var stmt *sql.Stmt
var err error
stmt, err = DB.Prepare(querysql)
return stmt, err
}
/**
* 执行自定义查询
* @return lastId error
*/
func QueryByStmt(sql string, valuelist []interface{}) ([]map[string]string, error) {
stmt, err := StmtForQuery(sql)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryList(stmt, valuelist)
}
/**
* 联表查询
* @param dbName
* @param tableA 表一
* @param tableA_alias 表一别名
* @param tableB 表二
* @param tableB_alias 表二别名
* @param join 联表方式
* @param join_on 联表字段
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* @param page 查询范围可传两个值 pageNum,pageSize
* GZ
* 2020/11/23
*/
func GetJoinListByStmt(dbName string, tableA, tableA_alias string, tableB, tableB_alias string, join_type, join_on string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) {
if len(page) > 0 {
pageNum, pageSize := page[0], 10
if len(page) > 1 {
pageSize = page[1]
}
limit["from"], limit["offset"] = GetPage(pageNum, pageSize)
}
if tableA_alias != "" {
tableA = StringJoin(dbName, ".", tableA, " as ", tableA_alias)
}
if tableB_alias != "" {
tableB = StringJoin(dbName, ".", tableB, " as ", tableB_alias)
}
table := StringJoin(tableA, " ", join_type, " join ", tableB, " on ", join_on)
stmt, err := StmtForRead(dbName, table, title, where, limit)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryList(stmt, valuelist)
}
/**
* 左联表查询
* @param dbName
* @param tableA 表一
* @param tableB 表二
* @param join_on 联表字段
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* @param page 查询范围可传两个值 pageNum,pageSize
* GZ
* 2021/1/27
*/
func LeftJoinListByStmt(dbName string, tableA, tableB string, join_on string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) {
if len(page) > 0 {
pageNum, pageSize := page[0], 10
if len(page) > 1 {
pageSize = page[1]
}
limit["from"], limit["offset"] = GetPage(pageNum, pageSize)
}
tableA = getTableName(dbName, tableA)
tableB = getTableName(dbName, tableB)
table := StringJoin(tableA, " left join ", tableB, " on ", join_on)
stmt, err := StmtForRead(dbName, table, title, where, limit)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryList(stmt, valuelist)
}

+ 21
- 0
tencentdb/prepare_test.go View File

@ -0,0 +1,21 @@
package tencentdb
import (
"testing"
)
func Test_StmtForExec(t *testing.T) {
Connect("127.0.0.1", "root", "123456", "tetele_empty", "3306")
stmt, err := StmtForUpdate("dev_tetele_net", "ttl_xshop_order", []string{"user_id = ?", "pay_time = pay_time+1"}, []string{"id=1"})
if err != nil {
t.Error(err)
}
defer stmt.Close()
ret, err := StmtForUpdateExec(stmt, []interface{}{"1"})
t.Log(ret)
t.Log(err)
}

+ 167
- 0
tencentdb/string.go View File

@ -0,0 +1,167 @@
package tencentdb
import (
"fmt"
"log"
"strconv"
"strings"
)
/*
* 连接多个字符串
* 2019/05/05
*/
func StringJoin(s ...string) string {
var build strings.Builder
if len(s) > 0 {
for _, v := range s {
build.WriteString(v)
}
}
return build.String()
}
/**
* 字符串转大驼峰 ios_bbbbbbbb -> IosBbbbbbbbb
*/
func StrFirstToUpper(str string) string {
str = strings.ReplaceAll(str, "`", "")
temp := strings.Split(str, "_")
var upperStr string
for y := 0; y < len(temp); y++ {
vv := []rune(temp[y])
for i := 0; i < len(vv); i++ {
if i == 0 {
vv[i] -= 32
upperStr += string(vv[i])
} else {
upperStr += string(vv[i])
}
}
}
return upperStr
}
func ToString(v interface{}) string {
var value string
switch v.(type) {
case string:
value = v.(string)
case int:
value = strconv.Itoa(v.(int))
case float64:
value = strconv.FormatFloat(v.(float64), 'f', 2, 64)
case float32:
value = strconv.FormatFloat(float64(v.(float32)), 'f', 2, 64)
case int64:
value = strconv.FormatInt(v.(int64), 10)
case []uint8:
value = string(v.([]uint8))
// case []byte:
// value = string(v.([]byte))
case interface{}:
value = v.(string)
case nil:
value = ""
default:
log.Println("参数值类型错误", v, "not in string|int|float64|interface|int64")
}
return strings.Trim(value, " ")
}
/**
* 是否存在在字符切片中
*/
func IsInStringArray(arr []string, str string) bool {
var isIn bool = false
length := len(arr)
if length < 1 {
return false
}
for _, item := range arr {
if item == str {
isIn = true
break
}
}
return isIn
}
func ToInt(inter interface{}) int {
var value int
switch inter.(type) {
case string:
value, _ = strconv.Atoi(inter.(string))
case int:
value = inter.(int)
case int64:
value = int(inter.(int64))
case float64:
value, _ = strconv.Atoi(fmt.Sprintf("%1.0f", inter))
case nil:
value = 0
case interface{}:
value = inter.(int)
default:
log.Println("参数值类型错误", inter, "not in string|int|float64|interface|int64")
}
return value
}
func ToInt64(inter interface{}) int64 {
var value int64
switch inter.(type) {
case string:
value, _ = strconv.ParseInt(inter.(string), 10, 64)
case int:
value = int64(inter.(int))
case int64:
value = inter.(int64)
case float64:
value_int, _ := strconv.Atoi(fmt.Sprintf("%1.0f", inter))
value = int64(value_int)
case nil:
value = 0
case interface{}:
if _, ok := inter.(int64); !ok {
value = inter.(int64)
}
default:
log.Println("参数值类型错误", inter, "not in string|int|float64|interface|int64")
}
return value
}
/**
* 根据第几页计算从第几行开始
* @param pageNum 第几页
* @param pageSize 每页几行
* @return from,offset 开始行数偏移量
* 2020/05/15
* gz
*/
func GetPage(pageNum, pageSize interface{}) (string, string) {
var from string
var offset int = ToInt(pageSize)
var pageNumInt, pageSizeInt int = ToInt(pageNum), ToInt(pageSize)
if pageNumInt < 1 {
pageNumInt = 1
}
if pageSizeInt < 1 {
offset = 10
pageSizeInt = 10
}
from = ToString((pageNumInt - 1) * pageSizeInt)
return from, ToString(offset)
}

+ 301
- 0
tencentdb/transaction.go View File

@ -0,0 +1,301 @@
/**
* DB transaction
*/
package tencentdb
import (
"database/sql"
"errors"
"log"
"strings"
"time"
)
/**
* 创建数据
*/
func TxInsert(tx *sql.Tx, dbname, table string, data map[string]string) (int64, error) {
var insertId int64
var err error
if dbname == "" && table == "" {
return 0, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
if len(data) < 1 {
return 0, errors.New("参数错误,没有要写入的数据")
}
keyList := make([]string, len(data))
keyStr := make([]string, len(data))
valueList := make([]interface{}, len(data))
var i int = 0
for key, value := range data {
keyList[i] = key
keyStr[i] = "?"
valueList[i] = value
i++
}
result, err := tx.Exec("insert into "+dbName+" ("+strings.Join(keyList, ",")+") value("+strings.Join(keyStr, ",")+")", valueList...)
if err != nil {
log.Println("ERROR", "insert into ", dbName, "error:", err)
return insertId, err
} else {
insertId, _ = result.LastInsertId()
time.Sleep(time.Second * 2)
return insertId, nil
}
}
/**
* 准备写入
* return Stmt error
*/
func TxPreInsert(tx *sql.Tx, dbname, table string, data map[string]interface{}) (int64, error) {
if dbname == "" && table == "" {
return 0, errors.New("params error,no db or table")
}
dbName := getTableName(dbname, table)
if len(data) < 1 {
return 0, errors.New("params error,no data to insert")
}
var err error
var stmt *sql.Stmt
var field []string = make([]string, len(data))
var valuelist []interface{} = make([]interface{}, len(data))
var i int = 0
for key, item := range data {
field[i] = key + "=?"
valuelist[i] = item
i++
}
sql := "insert into " + dbName + " set " + strings.Join(field, " , ")
stmt, err = tx.Prepare(sql)
if err != nil {
log.Println("insert prepare error:", sql, err)
return 0, errors.New("insert prepare error:" + err.Error())
}
result, err := stmt.Exec(valuelist...)
if err != nil {
log.Println("insert exec error:", sql, valuelist, err)
return 0, errors.New("insert exec error:" + err.Error())
}
insertId, _ := result.LastInsertId()
return insertId, nil
}
/**
* 修改数据
*/
func TxUpdate(tx *sql.Tx, dbname, table string, data map[string]string, where map[string]string) (int64, error) {
var rowsAffected int64
var err error
if dbname == "" && table == "" {
return rowsAffected, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
if len(data) < 1 {
return rowsAffected, errors.New("参数错误,没有要写入的数据")
}
if len(where) < 1 {
return rowsAffected, errors.New("参数错误,没有修改条件")
}
keyList := make([]string, len(data))
valueList := make([]interface{}, len(data), len(data)+len(where))
whereStr := make([]string, len(where))
var i int = 0
empty := false
for key, value := range data {
keyList[i] = key + "=?"
valueList[i] = value
i++
}
i = 0
for key, value := range where {
if value == "" {
empty = true
break
}
whereStr[i] = key + "=?"
valueList = append(valueList, value)
i++
}
if empty {
log.Println("ERROR", "update", dbName, "error, params empty")
return rowsAffected, errors.New("params empty")
}
result, err := tx.Exec("update "+dbName+" set "+strings.Join(keyList, " , ")+" where "+strings.Join(whereStr, " and "), valueList...)
if err != nil {
log.Println("ERROR", "update", dbName, "error:", err)
return rowsAffected, err
} else {
rowsAffected, _ = result.RowsAffected()
return rowsAffected, nil
}
}
/**
* 准备更新
* return Stmt error
*/
func TxPreUpdate(tx *sql.Tx, dbname, table string, data []string, where []string, valuelist []interface{}) (int64, error) {
if dbname == "" && table == "" {
return 0, errors.New("params error,no db or table")
}
dbName := getTableName(dbname, table)
if len(where) < 1 {
return 0, errors.New("params error, no data for update")
}
var err error
var stmt *sql.Stmt
sql := "update " + dbName + " set " + strings.Join(data, " , ") + " where " + strings.Join(where, " and ")
stmt, err = tx.Prepare(sql)
if err != nil {
log.Println("update prepare error:", sql, err)
return 0, errors.New("update prepare error:" + err.Error())
}
res, err := stmt.Exec(valuelist...)
if err != nil {
log.Println("update exec error:", sql, valuelist, err)
return 0, errors.New("update exec error:" + err.Error())
}
return res.RowsAffected()
}
/**
* 删除数据
* @param count 删除数量
*/
func TxDelete(tx *sql.Tx, dbname, table string, where map[string]string, del_count ...string) (int64, error) {
var count int64
var err error
if dbname == "" && table == "" {
return count, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
if len(where) < 1 {
return count, errors.New("参数错误,没有删除条件")
}
keyList := make([]string, len(where))
valueList := make([]interface{}, len(where))
var i int = 0
empty := false
for key, value := range where {
if value == "" {
empty = true
break
}
keyList[i] = key + "=?"
valueList[i] = value
i++
}
if empty {
log.Println("ERROR", "delete from", dbName, "error, where:", where)
return count, errors.New("params empty")
}
var limitStr string = ""
if len(del_count) > 0 {
limitStr = " limit " + del_count[0]
}
result, err := tx.Exec("delete from "+dbName+" where "+strings.Join(keyList, " and ")+limitStr, valueList...)
if err != nil {
log.Println("ERROR", "delete from", dbName, "error:", err)
return count, err
} else {
count, _ = result.RowsAffected()
return count, nil
}
}
/**
* 准备查询
* return Stmt error
*/
func TxForRead(tx *sql.Tx, dbName, table string, title string, where []string) (*sql.Stmt, error) {
if dbName == "" && table == "" {
return nil, errors.New("参数错误,没有数据表")
}
dbName = getTableName(dbName, table)
if len(title) < 1 {
return nil, errors.New("没有要查询内容")
}
var stmt *sql.Stmt
var err error
if len(where) > 0 {
// log.Println("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + " FOR UPDATE")
stmt, err = tx.Prepare("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + " FOR UPDATE")
} else {
// log.Println("SELECT " + title + " FROM " + dbName + " FOR UPDATE")
stmt, err = tx.Prepare("SELECT " + title + " FROM " + dbName + " FOR UPDATE")
}
return stmt, err
}
/**
* 使用db prepare方式查询单条数据
* @param dbName
* @param title 查询的字段名
* @param where 查询条件
* @param valuelist 查询的条件值
* @param limit 查询排序
* GZ
* 2020/05/19
*/
func TxGetData(tx *sql.Tx, dbName string, table string, title string, where []string, valuelist []interface{}) (map[string]string, error) {
stmt, err := TxForRead(tx, dbName, table, title, where)
if err != nil {
return nil, err
}
defer stmt.Close()
return StmtForQueryRow(stmt, valuelist)
}

+ 451
- 0
tencentdb/transaction_chain.go View File

@ -0,0 +1,451 @@
package tencentdb
/**
* 事务操作
*/
import (
"database/sql"
"errors"
"log"
"strconv"
"strings"
)
type TxQuery struct {
dbname string
table string
alias string
title string
where []string
where_or []string
join [][]string //[["tablea as a","a.id=b.id","left"]]
data []string
value []interface{}
orderby string
page int
page_size int
stmt *sql.Stmt
conn *sql.DB
tx *sql.Tx
debug bool
}
func NewTxQuery(t ...string) *TxQuery {
var conn_type *sql.DB = DB
tx, err := conn_type.Begin()
if err != nil {
log.Println("start tx begin error", err)
}
return &TxQuery{
conn: conn_type,
tx: tx,
}
}
func (this *TxQuery) Conn(conn *sql.DB) *TxQuery {
this.conn = conn
return this
}
func (this *TxQuery) Db(dbname string) *TxQuery {
this.dbname = dbname
return this
}
func (this *TxQuery) Table(tablename string) *TxQuery {
this.table = tablename
return this
}
func (this *TxQuery) Alias(tablename string) *TxQuery {
this.alias = tablename
return this
}
func (this *TxQuery) Title(title string) *TxQuery {
this.title = title
return this
}
func (this *TxQuery) Page(page int) *TxQuery {
this.page = page
return this
}
func (this *TxQuery) PageSize(page_num int) *TxQuery {
this.page_size = page_num
return this
}
func (this *TxQuery) Orderby(orderby string) *TxQuery {
this.orderby = orderby
return this
}
func (this *TxQuery) Where(where string) *TxQuery {
this.where = append(this.where, where)
return this
}
func (this *TxQuery) Wheres(wheres []string) *TxQuery {
if len(wheres) > 0 {
this.where = append(this.where, wheres...)
}
return this
}
func (this *TxQuery) WhereOr(where string) *TxQuery {
this.where_or = append(this.where_or, where)
return this
}
func (this *TxQuery) Value(value interface{}) *TxQuery {
this.value = append(this.value, value)
return this
}
func (this *TxQuery) Values(values []interface{}) *TxQuery {
this.value = append(this.value, values...)
return this
}
func (this *TxQuery) Join(join []string) *TxQuery {
this.join = append(this.join, join)
return this
}
func (this *TxQuery) Data(data string) *TxQuery {
this.data = append(this.data, data)
return this
}
func (this *TxQuery) Datas(datas []string) *TxQuery {
this.data = append(this.data, datas...)
return this
}
func (this *TxQuery) Debug(debug bool) *TxQuery {
this.debug = debug
return this
}
/*
* 清理上次查询
*/
func (this *TxQuery) Clean() *TxQuery {
this.title = ""
this.where = this.where[0:0]
this.where_or = this.where_or[0:0]
this.join = this.join[0:0]
this.data = this.data[0:0]
this.value = this.value[0:0]
this.orderby = ""
this.page = 0
this.page_size = 0
return this
}
// 拼查询sql
func (this *TxQuery) QueryStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
table := getTableName(this.dbname, this.table)
var sql, title string
if this.title != "" {
title = this.title
} else {
title = "*"
}
sql = StringJoin("select ", title)
if this.alias != "" {
table = StringJoin(table, " as ", this.alias)
}
sql = StringJoin(sql, " from ", table)
if len(this.join) > 0 {
for _, joinitem := range this.join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql = StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql = StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(this.where) > 0 || len(this.where_or) > 0 {
sql = StringJoin(sql, " where ")
}
if len(this.where) > 0 {
sql = StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ")
}
if len(this.where_or) > 0 {
if len(this.where) > 0 {
sql = StringJoin(sql, " or ", strings.Join(this.where_or, " or "))
} else {
sql = StringJoin(sql, strings.Join(this.where_or, " or "))
}
}
if this.orderby != "" {
sql = StringJoin(sql, " order by ", this.orderby)
}
if this.page > 0 || this.page_size > 0 {
if this.page < 1 {
this.page = 1
}
if this.page_size < 1 {
this.page_size = 10
}
from := strconv.Itoa((this.page - 1) * this.page_size)
offset := strconv.Itoa(this.page_size)
if from != "" && offset != "" {
sql = StringJoin(sql, " limit ", from, " , ", offset)
}
}
if this.debug {
log.Println("query sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
stmt, err = this.tx.Prepare(sql + " FOR UPDATE")
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼更新sql
func (this *TxQuery) UpdateStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
if len(this.where) < 1 {
return errors.New("参数错误,缺少条件")
}
dbName := getTableName(this.dbname, this.table)
var sql string
sql = StringJoin("update ", dbName, " set ", strings.Join(this.data, " , "))
sql = StringJoin(sql, " where ", strings.Join(this.where, " and "))
if this.debug {
log.Println("update sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
stmt, err = this.tx.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼插入sql
func (this *TxQuery) CreateStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
dbName := getTableName(this.dbname, this.table)
var sql string
sql = StringJoin("insert into ", dbName, " set ", strings.Join(this.data, " , "))
if this.debug {
log.Println("insert sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
stmt, err = this.tx.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
// 拼删除sql
func (this *TxQuery) DeleteStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
if len(this.where) < 1 {
return errors.New("参数错误,缺少条件")
}
dbName := getTableName(this.dbname, this.table)
var sql string
sql = StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and "))
if this.page_size > 0 {
sql = StringJoin(sql, " limit ", strconv.Itoa(this.page_size))
}
if this.debug {
log.Println("delete sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
condition_len++
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
}
stmt, err = this.tx.Prepare(sql)
if err != nil {
return err
}
this.stmt = stmt
return nil
}
/**
* 执行查询列表
* return list error
*/
func (this *TxQuery) Select() ([]map[string]string, error) {
err := this.QueryStmt()
if err != nil {
return []map[string]string{}, err
}
if this.stmt == nil {
return []map[string]string{}, errors.New("缺少必要参数")
}
return StmtForQueryList(this.stmt, this.value)
}
/**
* 执行查询一条数据
* return row error
*/
func (this *TxQuery) Find() (map[string]string, error) {
this.page = 1
this.page_size = 1
err := this.QueryStmt()
if err != nil {
return map[string]string{}, err
}
if this.stmt == nil {
return nil, errors.New("缺少必要参数")
}
return StmtForQueryRow(this.stmt, this.value)
}
/**
* 执行更新
* return is_updated error
*/
func (this *TxQuery) Update() (int64, error) {
err := this.UpdateStmt()
if err != nil {
return 0, err
}
return StmtForUpdateExec(this.stmt, this.value)
}
/**
* 执行删除
* return is_delete error
*/
func (this *TxQuery) Delete() (int64, error) {
err := this.DeleteStmt()
if err != nil {
return 0, err
}
return StmtForUpdateExec(this.stmt, this.value)
}
/**
* 执行写入
* return is_insert error
*/
func (this *TxQuery) Create() (int64, error) {
err := this.CreateStmt()
if err != nil {
return 0, err
}
return StmtForInsertExec(this.stmt, this.value)
}
/**
* 提交
*/
func (this *TxQuery) Commit() error {
return this.tx.Commit()
}
/**
* 回滚
*/
func (this *TxQuery) Rollback() error {
return this.tx.Rollback()
}

Loading…
Cancel
Save