| @ -0,0 +1,79 @@ | |||||
| package dbquery | |||||
| import ( | |||||
| "database/sql" | |||||
| "log" | |||||
| "errors" | |||||
| "strings" | |||||
| "time" | |||||
| "git.tetele.net/tgo/helper" | |||||
| _ "github.com/go-sql-driver/mysql" | |||||
| ) | |||||
| var DB *sql.DB | |||||
| 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++ { | |||||
| time.Sleep(time.Second * 5) | |||||
| DB, dbConnErr = sql.Open("mysql", DBUSER+":"+DBPWD+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8") | |||||
| if dbConnErr != nil { | |||||
| log.Println("ERROR", "can not connect to Database, ", dbConnErr) | |||||
| } 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 getTableName(dbName, table string) string { | |||||
| if strings.Contains(table, ".") { | |||||
| return table | |||||
| } | |||||
| if dbName != "" { | |||||
| return helper.StringJoin(dbName, ".", table) | |||||
| } else { | |||||
| return table | |||||
| } | |||||
| } | |||||
| func GetDbTableName(dbName, table string) string { | |||||
| return getTableName(dbName, table) | |||||
| } | |||||
| func judg() []string { | |||||
| return []string{"=", ">", "<", "!=", "<=", ">="} | |||||
| } | |||||
| @ -0,0 +1,629 @@ | |||||
| package dbquery | |||||
| import ( | |||||
| "database/sql" | |||||
| "log" | |||||
| "errors" | |||||
| "strings" | |||||
| "time" | |||||
| "git.tetele.net/tgo/helper" | |||||
| _ "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 = helper.StrFirstToUpper(columns[i]) | |||||
| info[index] = helper.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 | |||||
| } | |||||
| 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 helper.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 = helper.StrFirstToUpper(columns[i]) | |||||
| record[index] = helper.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 helper.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 := helper.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 = helper.StrFirstToUpper(columns[i]) | |||||
| record[index] = helper.ToString(col) | |||||
| } | |||||
| } | |||||
| list = append(list, record) | |||||
| } | |||||
| return list, nil | |||||
| } | |||||
| @ -0,0 +1,11 @@ | |||||
| package dbquery | |||||
| import ( | |||||
| "testing" | |||||
| ) | |||||
| func Test_GetTotal(t *testing.T) { | |||||
| Connect() | |||||
| total := GetTotal("dev_tetel_net", TABLE_CONFIG, "id") | |||||
| t.Log(total) | |||||
| } | |||||
| @ -0,0 +1,458 @@ | |||||
| package dbquery | |||||
| import ( | |||||
| "database/sql" | |||||
| "errors" | |||||
| "log" | |||||
| "strings" | |||||
| "git.tetele.net/tgo/helper" | |||||
| ) | |||||
| /** | |||||
| * 准备查询 | |||||
| * 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 = helper.StrFirstToUpper(columns[i]) | |||||
| info[index] = helper.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 = helper.StrFirstToUpper(columns[i]) | |||||
| info[index] = helper.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"] = helper.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"] = helper.GetPage(pageNum, pageSize) | |||||
| } | |||||
| if tableA_alias != "" { | |||||
| tableA = helper.StringJoin(dbName, ".", tableA, " as ", tableA_alias) | |||||
| } | |||||
| if tableB_alias != "" { | |||||
| tableB = helper.StringJoin(dbName, ".", tableB, " as ", tableB_alias) | |||||
| } | |||||
| table := helper.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"] = helper.GetPage(pageNum, pageSize) | |||||
| } | |||||
| tableA = getTableName(dbName, tableA) | |||||
| tableB = getTableName(dbName, tableB) | |||||
| table := helper.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) | |||||
| } | |||||
| @ -0,0 +1,21 @@ | |||||
| package dbquery | |||||
| 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) | |||||
| } | |||||
| @ -0,0 +1,301 @@ | |||||
| /** | |||||
| * DB transaction | |||||
| */ | |||||
| package dbquery | |||||
| 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) | |||||
| } | |||||