43 Commits

Author SHA1 Message Date
  loshiqi 5db8b87a21 transaction bug修复 1 day ago
  guzeng 6cc83234ed Merge branch 'master' of ssh://git.tetele.net:4001/tgo/dbquery 7 months ago
  guzeng 628562e53e 增加调试 7 months ago
  zhenghaorong 396b0b8f86 增加生成表名的函数 7 months ago
  guzeng f8d6d88e9f 增加左/右连接方法 8 months ago
  guzeng 2a1e8837ad Merge branch 'master' of ssh://git.tetele.net:4001/tgo/dbquery 9 months ago
  guzeng 0765adfb79 修改构造查询,兼容mssql的page size 9 months ago
  loshiqi db904d18e2 join兼容子查询 9 months ago
  zhenghaorong 373438a283 兼容多表名的情况 10 months ago
  guzeng 16ae9b2dbe 修改查询条件,兼容不同服务商数据库 1 year ago
  guzeng 0fe53a0d4f 修改事务写入 1 year ago
  guzeng 89c478b953 修改事务写入 1 year ago
  guzeng ff798de0a6 查询增加主从判断逻辑 1 year ago
  zhenghaorong 155e124c63 增加查询表格信息 1 year ago
  zhenghaorong 3d486e6fb8 增加查询表格信息 1 year ago
  zhenghaorong 2c7fb178b3 解决append顺序错乱问题 1 year ago
  zhenghaorong 00943e75ed 事务方法增加批量更新 1 year ago
  zhenghaorong 33971bf841 修改提示语 1 year ago
  zhenghaorong 4ac2e8c30d 增加批量更新 1 year ago
  zhenghaorong 0ccf9774b7 解决append乱序 1 year ago
  zhenghaorong cd13573588 增加批量添加 1 year ago
  zhenghaorong dcf3856862 增加批量添加 1 year ago
  zhenghaorong 6a197add57 增加批量添加 1 year ago
  zhenghaorong bb5a253e43 修改子查询带条件查询 1 year ago
  zhenghaorong f90aec27a3 添加子查询 1 year ago
  zhenghaorong 4f6940cc58 添加子查询 1 year ago
  zhenghaorong 8a4277f0eb 添加分组功能 1 year ago
  zhenghaorong 44c03e0282 增加分组功能 1 year ago
  guzeng 07e9c8a562 修改GetRow查询方法 2 years ago
  guzeng dc051970d3 增加从库查询 2 years ago
  guzeng c565655527 交换Find、Get方法,交换Select、List方法 2 years ago
  guzeng 302482fa54 chain.go增加直接查询数据方法Get(),List() 2 years ago
  listen 36fdaf99a8 尝试从读 2 years ago
  guzeng 75e7036854 修改连接charset 2 years ago
  guzeng da0617d167 事务单条查询增加默认条件 2 years ago
  guzeng 13587615a1 修改find方法 3 years ago
  guzeng abb2bbf3b5 关闭sqlserver连接修改 3 years ago
  guzeng c8293a8936 修改库连接操作 3 years ago
  guzeng 87001a68d4 增加事务链式操作 3 years ago
  guzeng 74d90296a6 修改连接 3 years ago
  guzeng c1a82cf1b0 修改查询 3 years ago
  guzeng f0254c8655 修改连接方法 3 years ago
  guzeng 6df1432cc1 增加sqlserver连接方法 3 years ago
11 changed files with 1968 additions and 70 deletions
Split View
  1. +530
    -39
      chain.go
  2. +4
    -2
      chain_test.go
  3. +83
    -9
      conn.go
  4. +352
    -8
      db.go
  5. +44
    -4
      db_test.go
  6. +1
    -0
      go.mod
  7. +7
    -0
      go.sum
  8. +0
    -0
      prepare.go
  9. +70
    -0
      sqlserver.go
  10. +35
    -8
      transaction.go
  11. +842
    -0
      transaction_chain.go

+ 530
- 39
chain.go View File

@ -3,6 +3,7 @@ package dbquery
import (
"database/sql"
"errors"
"log"
"strconv"
"strings"
@ -19,15 +20,51 @@ type Query struct {
title string
where []string
where_or []string
join [][]string //[["tablea as a","a.id=b.id","left"]]
join [][]string //[["tablea as a","a.id=b.id","left"]]
save_data []map[string]interface{} //批量操作的数据[["title":"a","num":1,],["title":"a","num":1,]]
upd_field []string // 批量更新时需要更新的字段,为空时按除id外的字段进行更新
data []string
value []interface{}
orderby string
groupby string
having string
page int
page_size int
stmt *sql.Stmt
conn *sql.DB
debug bool
dbtype string
}
func NewQuery(t ...string) *Query {
var conn_type *sql.DB = DB
var db_type string = "mysql"
if len(t) > 0 {
switch t[0] {
case "mysql":
conn_type = DB
db_type = "mysql"
case "mssql": //sql server
conn_type = MSDB_CONN
db_type = "mssql"
}
}
return &Query{
conn: conn_type,
dbtype: db_type,
}
}
func (this *Query) Conn(conn *sql.DB) *Query {
this.conn = conn
return this
}
func (this *Query) Db(dbname string) *Query {
this.dbname = dbname
return this
@ -54,11 +91,18 @@ func (this *Query) PageSize(page_num int) *Query {
this.page_size = page_num
return this
}
func (this *Query) Having(having string) *Query {
this.having = having
return this
}
func (this *Query) Orderby(orderby string) *Query {
this.orderby = orderby
return this
}
func (this *Query) Groupby(groupby string) *Query {
this.groupby = groupby
return this
}
func (this *Query) Where(where string) *Query {
this.where = append(this.where, where)
return this
@ -73,6 +117,22 @@ func (this *Query) WhereOr(where string) *Query {
this.where_or = append(this.where_or, where)
return this
}
func (this *Query) SaveData(value map[string]interface{}) *Query {
this.save_data = append(this.save_data, value)
return this
}
func (this *Query) SaveDatas(value []map[string]interface{}) *Query {
this.save_data = append(this.save_data, value...)
return this
}
func (this *Query) UpdField(value string) *Query {
this.upd_field = append(this.upd_field, value)
return this
}
func (this *Query) UpdFields(value []string) *Query {
this.upd_field = append(this.upd_field, value...)
return this
}
func (this *Query) Value(value interface{}) *Query {
this.value = append(this.value, value)
return this
@ -85,6 +145,27 @@ func (this *Query) Join(join []string) *Query {
this.join = append(this.join, join)
return this
}
/**
* 左连接
* 2023/08/10
* gz
*/
func (this *Query) LeftJoin(table_name string, condition string) *Query {
this.join = append(this.join, []string{table_name, condition, "left"})
return this
}
/**
* 右连接
* 2023/08/10
* gz
*/
func (this *Query) RightJoin(table_name string, condition string) *Query {
this.join = append(this.join, []string{table_name, condition, "right"})
return this
}
func (this *Query) Data(data string) *Query {
this.data = append(this.data, data)
return this
@ -94,22 +175,114 @@ func (this *Query) Datas(datas []string) *Query {
return this
}
// func (this *Query) Insert(where string) *Query {
// this.insert = append(this.insert, where)
// return this
// }
func (this *Query) Debug(debug bool) *Query {
this.debug = debug
return this
}
// 拼查询sql
func (this *Query) QueryStmt() error {
/*
* 清理上次查询
*/
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.groupby = ""
this.page = 0
this.page_size = 0
this.save_data = this.save_data[0:0]
this.upd_field = this.upd_field[0:0]
this.having = ""
this.alias = ""
return this
}
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
// 获取表格信息
func (this *Query) GetTableInfo(table string) (map[string]interface{}, error) {
field := []string{
"COLUMN_NAME", //字段名
"COLUMN_DEFAULT", //默认值
"DATA_TYPE", //数据类型
"COLUMN_TYPE", //数据类型+长度
"COLUMN_COMMENT", //备注
"IS_NULLABLE", //是否为空
}
sql := "select `" + strings.Join(field, "`,`") + "` from information_schema.COLUMNS where table_name = ? and table_schema = ?"
if this.conn == nil {
this.conn = DB
}
stmtSql, err := this.conn.Prepare(sql)
if err != nil {
return nil, err
}
// if len(this.where)+len(this.where_or) < len(this.value) {
// return errors.New("参数错误,条件值错误")
// }
list, err := StmtForQueryList(stmtSql, []interface{}{table, this.dbname})
if err != nil {
return nil, err
}
rows := make([]interface{}, 0, len(list))
fieldName := make([]string, 0, len(list))
for _, item := range list {
info := map[string]interface{}{
"name": "",
"column_type": "",
"is_null": true,
"data_type": "",
"comment": "",
"default": "",
}
for _, k := range field {
index := helper.StrFirstToUpper(k)
if v, ok := item[index]; ok {
switch k {
case "COLUMN_NAME":
info["name"] = v
case "COLUMN_DEFAULT":
info["default"] = v
case "DATA_TYPE":
info["data_type"] = v
case "COLUMN_TYPE":
info["column_type"] = helper.ToInt64(v)
case "COLUMN_COMMENT":
info["comment"] = helper.ToInt64(v)
case "IS_NULLABLE":
if v == "NO" {
info["is_null"] = false
}
}
}
}
name := helper.ToStr(info["name"])
if name != "" {
rows = append(rows, info)
fieldName = append(fieldName, name)
}
}
return map[string]interface{}{
"field": fieldName,
"list": rows,
}, nil
}
table := getTableName(this.dbname, this.table)
// 返回表名
func (this *Query) GetTableName(table string) string {
return getTableName(this.dbname, table)
}
// 构造子查询
func (this *Query) BuildSelectSql() (map[string]interface{}, error) {
if this.dbname == "" && this.table == "" {
return nil, errors.New("参数错误,没有数据表")
}
var table = ""
if strings.Contains(this.table, "select ") {
table = this.table
} else {
table = getTableName(this.dbname, this.table, this.dbtype)
}
// var err error
@ -120,7 +293,22 @@ func (this *Query) QueryStmt() error {
} else {
title = "*"
}
sql = helper.StringJoin("select ", title)
if this.dbtype == "mssql" {
if this.page_size > 0 {
sql = helper.StringJoin("select top ", helper.ToStr(this.page_size), " ")
} else {
sql = "select "
}
} else {
if DB_PROVIDER == "TencentDB" {
sql = "/*slave*/ select "
} else {
sql = "select "
}
}
sql = helper.StringJoin(sql, title)
if this.alias != "" {
table = helper.StringJoin(table, " as ", this.alias)
@ -129,15 +317,17 @@ func (this *Query) QueryStmt() error {
sql = helper.StringJoin(sql, " from ", table)
if len(this.join) > 0 {
join_type := "left"
for _, joinitem := range this.join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql = helper.StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
join_type = joinitem[2]
} else { //默认左连接
sql = helper.StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
join_type = "left"
}
sql = helper.StringJoin(sql, " ", join_type, " join ", getTableName(this.dbname, joinitem[0], this.dbtype), " on ", joinitem[1])
}
}
if len(this.where) > 0 || len(this.where_or) > 0 {
@ -153,12 +343,19 @@ func (this *Query) QueryStmt() error {
sql = helper.StringJoin(sql, strings.Join(this.where_or, " or "))
}
}
if this.groupby != "" {
sql = helper.StringJoin(sql, " group by ", this.groupby)
}
if this.having != "" {
sql = helper.StringJoin(sql, " having ", this.having)
}
if this.orderby != "" {
sql = helper.StringJoin(sql, " order by ", this.orderby)
}
if this.page > 0 || this.page_size > 0 {
if this.dbtype == "mysql" && (this.page > 0 || this.page_size > 0) {
if this.page < 1 {
this.page = 1
@ -172,7 +369,9 @@ func (this *Query) QueryStmt() error {
sql = helper.StringJoin(sql, " limit ", from, " , ", offset)
}
}
// log.Println(sql)
if this.debug {
log.Println("query sql:", sql, this.value)
}
condition_len := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
@ -180,10 +379,34 @@ func (this *Query) QueryStmt() error {
}
}
if condition_len != len(this.value) {
return errors.New("参数错误,条件值错误")
return nil, errors.New("参数错误,条件值错误")
}
return map[string]interface{}{
"sql": sql,
"value": this.value,
}, nil
}
// 拼查询sql
func (this *Query) QueryStmt() error {
res := map[string]interface{}{}
res, err = this.BuildSelectSql()
if err != nil {
return err
}
sql := helper.ToStr(res["sql"])
if SLAVER_DB != nil {
this.conn = SLAVER_DB
}
// else {
// this.conn = DB
// }
if this.conn == nil {
this.conn = DB
}
stmt, err = DB.Prepare(sql)
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
@ -204,10 +427,7 @@ func (this *Query) UpdateStmt() error {
return errors.New("参数错误,缺少条件")
}
dbName := getTableName(this.dbname, this.table)
// var stmt *sql.Stmt
// var err error
dbName := getTableName(this.dbname, this.table, this.dbtype)
var sql string
@ -215,6 +435,9 @@ func (this *Query) UpdateStmt() error {
sql = helper.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 {
@ -226,7 +449,11 @@ func (this *Query) UpdateStmt() error {
return errors.New("参数错误,条件值错误")
}
stmt, err = DB.Prepare(sql)
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
@ -237,8 +464,8 @@ func (this *Query) UpdateStmt() error {
return nil
}
// 拼插入sql
func (this *Query) CreateStmt() error {
// 拼批量存在更新不存在插入sql
func (this *Query) UpdateAllStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
@ -246,13 +473,224 @@ func (this *Query) CreateStmt() error {
dbName := getTableName(this.dbname, this.table)
// var stmt *sql.Stmt
// var err error
var sql string
var dataSql []string //一组用到的占位字符
var valSql []string //占位字符组
var updSql []string //更新字段的sql
var updFieldLen = len(this.upd_field) //需要更新的字段数量,为0时更新除id外添加值
dataLen := len(this.save_data)
if dataLen > 0 {
//批量操作
this.data = this.data[0:0]
this.value = this.value[0:0]
var dataSqlText string //占位字符组
for i := 0; i < dataLen; i++ {
if i == 0 {
//第一组时分配变量空间
fieldLen := len(this.save_data[i])
this.data = make([]string, 0, fieldLen)
dataSql = make([]string, 0, fieldLen)
this.value = make([]interface{}, 0, fieldLen*dataLen)
valSql = make([]string, 0, dataLen)
switch updFieldLen {
case 0:
//预览创建数据的长度
updSql = make([]string, 0, fieldLen)
default:
//按照需要更新字段数长度
updSql = make([]string, 0, updFieldLen)
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
}
}
for k := range this.save_data[i] {
this.data = append(this.data, k) //存储添加的字段
dataSql = append(dataSql, "?") //存储需要的占位符
if updFieldLen == 0 && k != "id" {
updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
}
}
dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
}
for j := 0; j < len(this.data); j++ {
this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
}
valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
}
} else {
//添加一条(原理同上)
fieldLen := len(this.data)
dataSql = make([]string, 0, fieldLen)
valSql = make([]string, 0, 1)
switch updFieldLen {
case 0:
updSql = make([]string, 0, fieldLen)
default:
updSql = make([]string, 0, updFieldLen)
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")")
}
}
for i := 0; i < fieldLen; i++ {
dataSql = append(dataSql, "?")
if updFieldLen == 0 && this.data[i] != "id" {
updSql = append(updSql, this.data[i]+"=values("+this.data[i]+")")
}
}
if updFieldLen > 0 {
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")")
}
}
valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
}
if len(this.data) == 0 {
return errors.New("参数错误,没有字段值")
}
if len(this.value) == 0 {
return errors.New("参数错误,条件值错误")
}
setText := " values "
if len(valSql) > 1 {
setText = " value "
}
sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","), " ON DUPLICATE KEY UPDATE ", strings.Join(updSql, " , "))
if this.debug {
log.Println("insert on duplicate key update sql:", sql, this.value)
}
conditionLen := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
conditionLen++
}
}
if conditionLen != 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) CreateAllStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
dbName := getTableName(this.dbname, this.table)
var sql string
var dataSql []string //一组用到的占位字符
var valSql []string //占位字符组
dataLen := len(this.save_data)
if dataLen > 0 {
//清空字段和值
this.data = this.data[0:0]
this.value = this.value[0:0]
var dataSqlText string //占位字符组
for i := 0; i < dataLen; i++ {
if i == 0 {
//第一组时分配变量空间
fieldLen := len(this.save_data[i])
this.data = make([]string, 0, fieldLen)
dataSql = make([]string, 0, fieldLen)
this.value = make([]interface{}, 0, fieldLen*dataLen)
valSql = make([]string, 0, dataLen)
for k := range this.save_data[i] {
this.data = append(this.data, k) //存储字段
dataSql = append(dataSql, "?") //存储需要的占位符
}
dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
}
for j := 0; j < len(this.data); j++ {
this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
}
valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
}
} else {
//添加一条(原理同上)
fieldLen := len(this.data)
dataSql = make([]string, 0, fieldLen)
for i := 0; i < fieldLen; i++ {
dataSql = append(dataSql, "?")
}
valSql = make([]string, 0, 1)
valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
}
if len(this.data) == 0 {
return errors.New("参数错误,字段名错误")
}
if len(this.value) == 0 {
return errors.New("参数错误,条件值错误")
}
//通过sql关键字优化批量操作和单个操作效率
setText := " values "
if len(valSql) > 1 {
setText = " value "
}
sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","))
if this.debug {
log.Println("insert sql:", sql, this.value)
}
conditionLen := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
conditionLen++
}
}
if conditionLen != 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 = helper.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 {
@ -264,7 +702,11 @@ func (this *Query) CreateStmt() error {
return errors.New("参数错误,条件值错误")
}
stmt, err = DB.Prepare(sql)
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
@ -284,14 +726,8 @@ func (this *Query) DeleteStmt() error {
if len(this.where) < 1 {
return errors.New("参数错误,缺少条件")
}
// if len(this.where) != len(this.value) {
// return errors.New("参数错误,条件值错误")
// }
dbName := getTableName(this.dbname, this.table)
// var stmt *sql.Stmt
// var err error
dbName := getTableName(this.dbname, this.table, this.dbtype)
var sql string
@ -301,6 +737,9 @@ func (this *Query) DeleteStmt() error {
sql = helper.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 {
@ -312,7 +751,11 @@ func (this *Query) DeleteStmt() error {
return errors.New("参数错误,条件值错误")
}
stmt, err = DB.Prepare(sql)
if this.conn == nil {
this.conn = DB
}
stmt, err = this.conn.Prepare(sql)
if err != nil {
return err
@ -329,6 +772,19 @@ func (this *Query) DeleteStmt() error {
*/
func (this *Query) Select() ([]map[string]string, error) {
_, rows, err := FetchRows(this.dbname, this.table, this.alias, this.title, this.join,
this.where, this.where_or, this.value, this.orderby, this.groupby, this.having, this.page, this.page_size, this.debug)
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
@ -347,6 +803,20 @@ func (this *Query) Select() ([]map[string]string, error) {
*/
func (this *Query) Find() (map[string]string, error) {
_, row, err := GetRow(this.dbname, this.table, this.alias, this.title, this.join,
this.where, this.where_or, this.value, this.orderby, this.groupby, this.having, this.debug)
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
@ -372,6 +842,17 @@ func (this *Query) Update() (int64, error) {
return StmtForUpdateExec(this.stmt, this.value)
}
// 批量更新
func (this *Query) UpdateAll() (int64, error) {
err := this.UpdateAllStmt()
if err != nil {
return 0, err
}
return StmtForUpdateExec(this.stmt, this.value)
}
/**
* 执行删除
* return is_delete error
@ -399,3 +880,13 @@ func (this *Query) Create() (int64, error) {
return StmtForInsertExec(this.stmt, this.value)
}
func (this *Query) CreateAll() (int64, error) {
err := this.CreateAllStmt()
if err != nil {
return 0, err
}
return StmtForInsertExec(this.stmt, this.value)
}

+ 4
- 2
chain_test.go View File

@ -5,9 +5,11 @@ import (
)
func Test_Chain(t *testing.T) {
Connect("127.0.0.1", "root", "123456", "test1_tetele_com", "3306")
Connect("127.0.0.1", "root", "123456", "shop", "3306")
ret, err := new(Query).Db("test1_tetele_com").Table("ttl_user").Title("id,username").WhereOr("id =?").WhereOr("id = ?").Value(2).Value(4).Value(4).PageSize(4).Select()
ret, err := new(Query).Db("shop").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).List()
t.Log(len(ret))
t.Log(ret)


+ 83
- 9
conn.go View File

@ -15,6 +15,11 @@ import (
var DB *sql.DB
var SLAVER_DB *sql.DB
// db类型,默认空,如TencentDB(腾讯),
var DB_PROVIDER string
func Connect(DBHOST, DBUSER, DBPWD, DBNAME, DBPORT string, conns ...int) error {
log.Println("database connectting...")
@ -22,10 +27,10 @@ func Connect(DBHOST, DBUSER, DBPWD, DBNAME, DBPORT string, conns ...int) error {
if DBHOST != "" && DBUSER != "" && DBPWD != "" && DBPORT != "" { //&& DBNAME != ""
for i := 0; i < 10; i++ {
time.Sleep(time.Second * 5)
DB, dbConnErr = sql.Open("mysql", DBUSER+":"+DBPWD+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8")
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表示不限制
@ -55,19 +60,88 @@ func CloseConn() error {
return DB.Close()
}
func ConnectSlaver(DBHOST, DBUSER_SLAVER, DBPWD_SLAVER, DBNAME, DBPORT string, conns ...int) error {
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 CloseSlaverConn() error {
return SLAVER_DB.Close()
}
/**
* 检测表名
*/
func getTableName(dbName, table string) string {
func getTableName(dbName, table string, dbtype ...string) string {
var db_type string = "mysql"
if strings.Contains(table, ".") {
return table
if len(dbtype) > 0 {
if dbtype[0] != "" {
db_type = dbtype[0]
}
}
if dbName != "" {
return helper.StringJoin(dbName, ".", table)
} else {
return table
var ret string
switch db_type {
case "mysql":
if strings.Contains(table, ".") {
ret = table
}
if dbName != "" {
if strings.Contains(table, ",") {
arr := strings.Split(table, ",")
arrStrs := make([]string, 0, len(arr))
for _, v := range arr {
arrStrs = append(arrStrs, helper.StringJoin(dbName, ".", v))
}
ret = strings.Join(arrStrs, ",")
} else {
ret = helper.StringJoin(dbName, ".", table)
}
} else {
ret = table
}
case "mssql":
ret = helper.StringJoin(dbName, ".", table)
}
return ret
}
func GetDbTableName(dbName, table string) string {


+ 352
- 8
db.go View File

@ -3,6 +3,7 @@ package dbquery
import (
"database/sql"
"log"
"strconv"
"errors"
"strings"
@ -22,7 +23,11 @@ func Insert(dbName, table string, data map[string]string) (int64, error) {
if dbName == "" && table == "" {
return insertId, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
if len(data) < 1 {
return insertId, errors.New("没有要写入的数据")
@ -63,7 +68,11 @@ func Update(dbName, table string, data map[string]string, where map[string]strin
return rowsAffected, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
if len(data) < 1 {
return rowsAffected, errors.New("同有更新的数据")
}
@ -123,8 +132,11 @@ func Delete(dbName, table string, data map[string]string, del_count ...string) (
return count, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
if len(data) < 1 {
return count, errors.New("没有要删除的数据")
}
@ -277,6 +289,327 @@ func GetData(dbName, table string, title string, where map[string]string, limit
return count, info, nil
}
/**
* 查找一条记录
* @param dbName 数据表名
* @param title 查询字段名
*/
func GetRow(dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby, groupby, having 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 := ""
if strings.Contains(table_name, "select ") {
table = table_name
} else {
table = getTableName(dbName, table_name)
}
var sql_str, title string
if titles != "" {
title = titles
} else {
title = "*"
}
if DB_PROVIDER == "TencentDB" {
sql_str = helper.StringJoin("/*slave*/ select ", title)
} else {
sql_str = helper.StringJoin("select ", title)
}
if alias != "" {
table = helper.StringJoin(table, " as ", alias)
}
sql_str = helper.StringJoin(sql_str, " from ", table)
if len(join) > 0 {
for _, joinitem := range join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 4 {
sql_str = helper.StringJoin(sql_str, " ", joinitem[2], " join ", joinitem[0], " on ", joinitem[1])
} else if len(joinitem) == 3 {
sql_str = helper.StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql_str = helper.StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(where) > 0 || len(where_or) > 0 {
sql_str = helper.StringJoin(sql_str, " where ")
}
if len(where) > 0 {
sql_str = helper.StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ")
}
if len(where_or) > 0 {
if len(where) > 0 {
sql_str = helper.StringJoin(sql_str, " or ", strings.Join(where_or, " or "))
} else {
sql_str = helper.StringJoin(sql_str, strings.Join(where_or, " or "))
}
}
if groupby != "" {
sql_str = helper.StringJoin(sql_str, " group by ", groupby)
}
if having != "" {
sql_str = helper.StringJoin(sql_str, " having ", having)
}
if orderby != "" {
sql_str = helper.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 = helper.StringJoin(sql_str, " limit 1")
var db *sql.DB
if SLAVER_DB != nil {
db = SLAVER_DB
} else {
db = DB
}
for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题
rows, err = db.Query(sql_str, valueList...)
if err == nil {
break
} else {
log.Println(err)
time.Sleep(time.Millisecond * 500)
}
queryNum++
}
if err != nil {
log.Println("DB error:", err)
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 = helper.StrFirstToUpper(columns[i])
info[index] = helper.ToString(col)
}
}
count++
} else {
log.Println("ERROR", rowerr)
}
}
rows.Close()
if rowerr != nil {
log.Println("DB row error:", rowerr)
return count, info, rowerr
}
return count, info, nil
}
/**
* 查找多条记录
* @param dbName 数据表名
* @param title 查询字段名
*/
func FetchRows(dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby, groupby, having 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 := ""
if strings.Contains(table_name, "select ") {
table = table_name
} else {
table = getTableName(dbName, table_name)
}
var sql_str, title string
if titles != "" {
title = titles
} else {
title = "*"
}
if DB_PROVIDER == "TencentDB" {
sql_str = helper.StringJoin("/*slave*/ select ", title)
} else {
sql_str = helper.StringJoin("select ", title)
}
if alias != "" {
table = helper.StringJoin(table, " as ", alias)
}
sql_str = helper.StringJoin(sql_str, " from ", table)
if len(join) > 0 {
for _, joinitem := range join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 4 {
sql_str = helper.StringJoin(sql_str, " ", joinitem[2], " join ", joinitem[0], " on ", joinitem[1])
} else if len(joinitem) == 3 {
sql_str = helper.StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql_str = helper.StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(where) > 0 || len(where_or) > 0 {
sql_str = helper.StringJoin(sql_str, " where ")
}
if len(where) > 0 {
sql_str = helper.StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ")
}
if len(where_or) > 0 {
if len(where) > 0 {
sql_str = helper.StringJoin(sql_str, " or ", strings.Join(where_or, " or "))
} else {
sql_str = helper.StringJoin(sql_str, strings.Join(where_or, " or "))
}
}
if groupby != "" {
sql_str = helper.StringJoin(sql_str, " group by ", groupby)
}
if having != "" {
sql_str = helper.StringJoin(sql_str, " HAVING ", having)
}
if orderby != "" {
sql_str = helper.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 = helper.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 db *sql.DB
if SLAVER_DB != nil {
db = SLAVER_DB
} else {
db = DB
}
var rows *sql.Rows
var err error
var queryNum int = 0
for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题
rows, err = db.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 = helper.StrFirstToUpper(columns[i])
info[index] = helper.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)
@ -302,8 +635,11 @@ func GetList(dbName, table string, title string, where map[string]string, limit
return list, errors.New("没有数据表")
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
var rows *sql.Rows
var err error
var queryNum int = 0
@ -426,7 +762,11 @@ func GetTotal(dbName, table string, args ...string) (total int) {
return
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
var title string = "*"
@ -480,7 +820,11 @@ func GetCount(dbName, table string, where map[string]string, args ...string) (to
if dbName == "" && table == "" {
return
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
var title string = "*"


+ 44
- 4
db_test.go View File

@ -1,11 +1,51 @@
package dbquery
import (
"log"
"testing"
)
func Test_GetTotal(t *testing.T) {
Connect()
total := GetTotal("dev_tetel_net", TABLE_CONFIG, "id")
t.Log(total)
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())
}
}
//}()
}

+ 1
- 0
go.mod View File

@ -4,5 +4,6 @@ go 1.14
require (
git.tetele.net/tgo/helper v0.1.0
github.com/denisenkom/go-mssqldb v0.11.0
github.com/go-sql-driver/mysql v1.5.0
)

+ 7
- 0
go.sum View File

@ -1,4 +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=

+ 0
- 0
prepare.go View File


+ 70
- 0
sqlserver.go View File

@ -0,0 +1,70 @@
package dbquery
import (
"database/sql"
"errors"
"fmt"
"strconv"
"log"
"time"
_ "github.com/denisenkom/go-mssqldb"
)
var MSDB_CONN *sql.DB
func MSConnect(DBHOST, DBUSER, DBPWD, DBNAME, DBPORT, encrypt string, conns ...int) error {
log.Println("msdb connectting...")
var dbConnErr error
if DBHOST != "" && DBUSER != "" && DBPWD != "" && DBPORT != "" { //&& DBNAME != ""
for i := 0; i < 10; i++ {
//连接字符串
db_port, _ := strconv.Atoi(DBPORT)
params := "server=%s;port=%d;database=%s;user id=%s;password=%s"
if encrypt != "" {
params = params + ";encrypt=" + encrypt
}
connString := fmt.Sprintf(params, DBHOST, db_port, DBNAME, DBUSER, DBPWD)
log.Println(connString)
//建立连接
MSDB_CONN, dbConnErr = sql.Open("mssql", connString)
if dbConnErr != nil {
log.Println("ERROR", "can not connect to Database, ", dbConnErr)
time.Sleep(time.Second * 5)
} else {
err = MSDB_CONN.Ping()
log.Println("msdb connected", err)
break
}
}
} else {
return errors.New("msdb connection params errors")
}
return dbConnErr
}
func CloseMSConn() error {
if MSDB_CONN != nil {
return MSDB_CONN.Close()
}
return nil
}

+ 35
- 8
transaction.go View File

@ -21,7 +21,12 @@ func TxInsert(tx *sql.Tx, dbname, table string, data map[string]string) (int64,
if dbname == "" && table == "" {
return 0, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
dbName := ""
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbname, table)
}
if len(data) < 1 {
return 0, errors.New("参数错误,没有要写入的数据")
}
@ -62,7 +67,12 @@ func TxPreInsert(tx *sql.Tx, dbname, table string, data map[string]interface{})
return 0, errors.New("params error,no db or table")
}
dbName := getTableName(dbname, table)
dbName := ""
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbname, table)
}
if len(data) < 1 {
return 0, errors.New("params error,no data to insert")
@ -108,7 +118,12 @@ func TxUpdate(tx *sql.Tx, dbname, table string, data map[string]string, where ma
if dbname == "" && table == "" {
return rowsAffected, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
dbName := ""
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbname, table)
}
if len(data) < 1 {
return rowsAffected, errors.New("参数错误,没有要写入的数据")
}
@ -167,7 +182,12 @@ func TxPreUpdate(tx *sql.Tx, dbname, table string, data []string, where []string
return 0, errors.New("params error,no db or table")
}
dbName := getTableName(dbname, table)
dbName := ""
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbname, table)
}
if len(where) < 1 {
return 0, errors.New("params error, no data for update")
@ -204,8 +224,12 @@ func TxDelete(tx *sql.Tx, dbname, table string, where map[string]string, del_cou
if dbname == "" && table == "" {
return count, errors.New("参数错误,没有数据表")
}
dbName := getTableName(dbname, table)
dbName := ""
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbname, table)
}
if len(where) < 1 {
return count, errors.New("参数错误,没有删除条件")
}
@ -257,8 +281,11 @@ func TxForRead(tx *sql.Tx, dbName, table string, title string, where []string) (
if dbName == "" && table == "" {
return nil, errors.New("参数错误,没有数据表")
}
dbName = getTableName(dbName, table)
if strings.Contains(table, "select ") {
dbName = table
} else {
dbName = getTableName(dbName, table)
}
if len(title) < 1 {
return nil, errors.New("没有要查询内容")


+ 842
- 0
transaction_chain.go View File

@ -0,0 +1,842 @@
package dbquery
/**
* 事务操作
*/
import (
"database/sql"
"errors"
"log"
"strconv"
"strings"
"git.tetele.net/tgo/helper"
)
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{}
save_data []map[string]interface{} //批量操作的数据[["title":"a","num":1,],["title":"a","num":1,]]
upd_field []string // 批量更新时需要更新的字段,为空时按除id外的字段进行更新
orderby string
groupby string
having 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
if len(t) > 0 {
switch t[0] {
case "mysql":
conn_type = DB
case "mssql": //sql server
conn_type = MSDB_CONN
}
}
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) Groupby(groupby string) *TxQuery {
this.groupby = groupby
return this
}
func (this *TxQuery) Having(having string) *TxQuery {
this.having = having
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) SaveData(value map[string]interface{}) *TxQuery {
this.save_data = append(this.save_data, value)
return this
}
func (this *TxQuery) SaveDatas(value []map[string]interface{}) *TxQuery {
this.save_data = append(this.save_data, value...)
return this
}
func (this *TxQuery) UpdField(value string) *TxQuery {
this.upd_field = append(this.upd_field, value)
return this
}
func (this *TxQuery) UpdFields(value []string) *TxQuery {
this.upd_field = append(this.upd_field, 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
}
/**
* 左连接
* 2023/08/10
* gz
*/
func (this *TxQuery) LeftJoin(table_name string, condition string) *TxQuery {
this.join = append(this.join, []string{table_name, condition, "left"})
return this
}
/**
* 右连接
* 2023/08/10
* gz
*/
func (this *TxQuery) RightJoin(table_name string, condition string) *TxQuery {
this.join = append(this.join, []string{table_name, condition, "right"})
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.groupby = ""
this.page = 0
this.page_size = 0
this.save_data = this.save_data[0:0]
this.upd_field = this.upd_field[0:0]
this.having = ""
this.alias = ""
return this
}
// 返回表名
func (this *TxQuery) GetTableName(table string) string {
return getTableName(this.dbname, table)
}
// 构造子查询
func (this *TxQuery) BuildSelectSql() (map[string]interface{}, error) {
if this.dbname == "" && this.table == "" {
return nil, errors.New("参数错误,没有数据表")
}
var table = ""
if strings.Contains(this.table, "select ") {
table = this.table
} else {
table = getTableName(this.dbname, this.table)
}
var sql, title string
if this.title != "" {
title = this.title
} else {
title = "*"
}
sql = helper.StringJoin("select ", title)
if this.alias != "" {
table = helper.StringJoin(table, " as ", this.alias)
}
sql = helper.StringJoin(sql, " from ", table)
if len(this.join) > 0 {
for _, joinitem := range this.join {
if len(joinitem) < 2 {
continue
}
if len(joinitem) == 3 {
sql = helper.StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
} else { //默认左连接
sql = helper.StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1])
}
}
}
if len(this.where) > 0 || len(this.where_or) > 0 {
sql = helper.StringJoin(sql, " where ")
}
if len(this.where) > 0 {
sql = helper.StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ")
}
if len(this.where_or) > 0 {
if len(this.where) > 0 {
sql = helper.StringJoin(sql, " or ", strings.Join(this.where_or, " or "))
} else {
sql = helper.StringJoin(sql, strings.Join(this.where_or, " or "))
}
}
if this.groupby != "" {
sql = helper.StringJoin(sql, " group by ", this.groupby)
}
if this.having != "" {
sql = helper.StringJoin(sql, " having ", this.having)
}
if this.orderby != "" {
sql = helper.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 = helper.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 nil, errors.New("参数错误,条件值错误")
}
return map[string]interface{}{
"sql": sql,
"value": this.value,
}, nil
}
// 获取表格信息
func (this *TxQuery) GetTableInfo(table string) (map[string]interface{}, error) {
field := []string{
"COLUMN_NAME", //字段名
"COLUMN_DEFAULT", //默认值
"DATA_TYPE", //数据类型
"COLUMN_TYPE", //数据类型+长度
"COLUMN_COMMENT", //备注
"IS_NULLABLE", //是否为空
}
sql := "select `" + strings.Join(field, "`,`") + "` from information_schema.COLUMNS where table_name = ? and table_schema = ?"
stmtSql, err := this.tx.Prepare(sql)
if err != nil {
return nil, err
}
list, err := StmtForQueryList(stmtSql, []interface{}{table, this.dbname})
if err != nil {
return nil, err
}
rows := make([]interface{}, 0, len(list))
fieldName := make([]string, 0, len(list))
for _, item := range list {
info := map[string]interface{}{
"name": "",
"column_type": "",
"is_null": true,
"data_type": "",
"comment": "",
"default": "",
}
for _, k := range field {
index := helper.StrFirstToUpper(k)
if v, ok := item[index]; ok {
switch k {
case "COLUMN_NAME":
info["name"] = v
case "COLUMN_DEFAULT":
info["default"] = v
case "DATA_TYPE":
info["data_type"] = v
case "COLUMN_TYPE":
info["column_type"] = helper.ToInt64(v)
case "COLUMN_COMMENT":
info["comment"] = helper.ToInt64(v)
case "IS_NULLABLE":
if v == "NO" {
info["is_null"] = false
}
}
}
}
name := helper.ToStr(info["name"])
if name != "" {
rows = append(rows, info)
fieldName = append(fieldName, name)
}
}
return map[string]interface{}{
"field": fieldName,
"list": rows,
}, nil
}
// 拼查询sql
func (this *TxQuery) QueryStmt() error {
res := map[string]interface{}{}
res, err = this.BuildSelectSql()
if err != nil {
return err
}
sql := helper.ToStr(res["sql"])
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 = helper.StringJoin("update ", dbName, " set ", strings.Join(this.data, " , "))
sql = helper.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) UpdateAllStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
dbName := getTableName(this.dbname, this.table)
var sql string
var dataSql []string //一组用到的占位字符
var valSql []string //占位字符组
var updSql []string //更新字段的sql
var updFieldLen = len(this.upd_field) //需要更新的字段数量,为0时更新除id外添加值
dataLen := len(this.save_data)
if dataLen > 0 {
//批量操作
this.data = this.data[0:0]
this.value = this.value[0:0]
var dataSqlText string //占位字符组
for i := 0; i < dataLen; i++ {
if i == 0 {
//第一组时分配变量空间
fieldLen := len(this.save_data[i])
this.data = make([]string, 0, fieldLen)
dataSql = make([]string, 0, fieldLen)
this.value = make([]interface{}, 0, fieldLen*dataLen)
valSql = make([]string, 0, dataLen)
switch updFieldLen {
case 0:
//预览创建数据的长度
updSql = make([]string, 0, fieldLen)
default:
//按照需要更新字段数长度
updSql = make([]string, 0, updFieldLen)
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
}
}
for k := range this.save_data[i] {
this.data = append(this.data, k) //存储添加的字段
dataSql = append(dataSql, "?") //存储需要的占位符
if updFieldLen == 0 && k != "id" {
updSql = append(updSql, k+"=values("+k+")") //存储需要更新的字段
}
}
dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
}
for j := 0; j < len(this.data); j++ {
this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
}
valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
}
} else {
//添加一条(原理同上)
fieldLen := len(this.data)
dataSql = make([]string, 0, fieldLen)
valSql = make([]string, 0, 1)
switch updFieldLen {
case 0:
updSql = make([]string, 0, fieldLen)
default:
updSql = make([]string, 0, updFieldLen)
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")")
}
}
for i := 0; i < fieldLen; i++ {
dataSql = append(dataSql, "?")
if updFieldLen == 0 && this.data[i] != "id" {
updSql = append(updSql, this.data[i]+"=values("+this.data[i]+")")
}
}
if updFieldLen > 0 {
for _, k := range this.upd_field {
updSql = append(updSql, k+"=values("+k+")")
}
}
valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
}
if len(this.data) == 0 {
return errors.New("参数错误,没有字段值")
}
if len(this.value) == 0 {
return errors.New("参数错误,条件值错误")
}
setText := " values "
if len(valSql) > 1 {
setText = " value "
}
sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","), " ON DUPLICATE KEY UPDATE ", strings.Join(updSql, " , "))
if this.debug {
log.Println("insert on duplicate key update sql:", sql, this.value)
}
conditionLen := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
conditionLen++
}
}
if conditionLen != 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 = helper.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) CreateAllStmt() error {
if this.dbname == "" && this.table == "" {
return errors.New("参数错误,没有数据表")
}
dbName := getTableName(this.dbname, this.table)
var sql string
var dataSql []string //一组用到的占位字符
var valSql []string //占位字符组
dataLen := len(this.save_data)
if dataLen > 0 {
//清空字段和值
this.data = this.data[0:0]
this.value = this.value[0:0]
var dataSqlText string //占位字符组
for i := 0; i < dataLen; i++ {
if i == 0 {
//第一组时分配变量空间
fieldLen := len(this.save_data[i])
this.data = make([]string, 0, fieldLen)
dataSql = make([]string, 0, fieldLen)
this.value = make([]interface{}, 0, fieldLen*dataLen)
valSql = make([]string, 0, dataLen)
for k := range this.save_data[i] {
this.data = append(this.data, k) //存储字段
dataSql = append(dataSql, "?") //存储需要的占位符
}
dataSqlText = strings.Join(dataSql, ",") //组成每组占位字符格式
}
for j := 0; j < len(this.data); j++ {
this.value = append(this.value, this.save_data[i][this.data[j]]) //存储值
}
valSql = append(valSql, "("+dataSqlText+")") //组成占位字符组
}
} else {
//添加一条(原理同上)
fieldLen := len(this.data)
dataSql = make([]string, 0, fieldLen)
for i := 0; i < fieldLen; i++ {
dataSql = append(dataSql, "?")
}
valSql = make([]string, 0, 1)
valSql = append(valSql, "("+strings.Join(dataSql, " , ")+")")
}
if len(this.data) == 0 {
return errors.New("参数错误,字段名错误")
}
if len(this.value) == 0 {
return errors.New("参数错误,条件值错误")
}
//通过sql关键字优化批量操作和单个操作效率
setText := " values "
if len(valSql) > 1 {
setText = " value "
}
sql = helper.StringJoin("insert into ", dbName, " (", strings.Join(this.data, " , "), ")", setText, strings.Join(valSql, ","))
if len(this.value) == 0 {
return errors.New("参数错误,条件值错误")
}
if this.debug {
log.Println("insert sql:", sql, this.value)
}
conditionLen := 0 //所有条件数
for _, ch2 := range sql {
if string(ch2) == "?" {
conditionLen++
}
}
if conditionLen != 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 = helper.StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and "))
if this.page_size > 0 {
sql = helper.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)
}
// UpdateAll 批量更新(根据唯一键判断存在则更新,不存在则创建)
func (this *TxQuery) UpdateAll() (int64, error) {
err := this.UpdateAllStmt()
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)
}
/**
* 执行批量写入
* return is_insert error
*/
func (this *TxQuery) CreateAll() (int64, error) {
err := this.CreateAllStmt()
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