From 26ad8c68f694ff3506963101f274cab48fb3700a Mon Sep 17 00:00:00 2001 From: guzeng Date: Wed, 2 Mar 2022 13:53:17 +0800 Subject: [PATCH] =?UTF-8?q?=E8=85=BE=E8=AE=AF=E4=BA=91mariadb=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- tencentdb/README.md | 32 ++ tencentdb/chain.go | 502 ++++++++++++++++++ tencentdb/chain_test.go | 21 + tencentdb/conn.go | 187 +++++++ tencentdb/db.go | 905 +++++++++++++++++++++++++++++++++ tencentdb/db_test.go | 51 ++ tencentdb/go.mod | 7 + tencentdb/go.sum | 11 + tencentdb/prepare.go | 456 +++++++++++++++++ tencentdb/prepare_test.go | 21 + tencentdb/string.go | 167 ++++++ tencentdb/transaction.go | 301 +++++++++++ tencentdb/transaction_chain.go | 451 ++++++++++++++++ 13 files changed, 3112 insertions(+) create mode 100644 tencentdb/README.md create mode 100644 tencentdb/chain.go create mode 100644 tencentdb/chain_test.go create mode 100755 tencentdb/conn.go create mode 100644 tencentdb/db.go create mode 100755 tencentdb/db_test.go create mode 100644 tencentdb/go.mod create mode 100644 tencentdb/go.sum create mode 100755 tencentdb/prepare.go create mode 100644 tencentdb/prepare_test.go create mode 100644 tencentdb/string.go create mode 100755 tencentdb/transaction.go create mode 100644 tencentdb/transaction_chain.go diff --git a/tencentdb/README.md b/tencentdb/README.md new file mode 100644 index 0000000..ac4dcea --- /dev/null +++ b/tencentdb/README.md @@ -0,0 +1,32 @@ +# dbquery + +腾讯云mariadb一主多从数据库操作 + +## 链式查询使用 +``` +查询单条记录 +map,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").Value(1).Value("test").Find() + + +查询列表 +list,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").Value(1).Value("test").Select() + +条件"或" +list,err := new(Query).Db(dbname).Table(tablename).Where("id=?").Where("name=?").WhereOr("mobile=?").Value(1).Value("test").Value("22").Select() + + +联表查 +使用Join + +list,err := new(Query).Db(dbname).Table(tablename).Join([]string{jointable,tablename.id=jointable.cid,"LEFT"}).Where("id=?").Where("name=?").Value(1).Value("test").Select() + +更新 +ret,err := new(Query).Db(dbname).Table(tablename).Data("name=?").Data("depart=?").Value("xxx").Value("test").Update() + + +插入 +ret,err := new(Query).Db(dbname).Table(tablename).Data("name=?").Data("depart=?").Value("xxx").Value("test").Create() + +删除 +ret,err := new(Query).Db(dbname).Table(tablename).Where("name=?").Where("depart=?").Value("xxx").Value("test").Delete() +``` diff --git a/tencentdb/chain.go b/tencentdb/chain.go new file mode 100644 index 0000000..1e1162f --- /dev/null +++ b/tencentdb/chain.go @@ -0,0 +1,502 @@ +package tencentdb + +import ( + "database/sql" + "errors" + "log" + "strconv" + "strings" +) + +var stmt *sql.Stmt +var err error + +type Query struct { + dbname string + table string + alias string + title string + where []string + where_or []string + join [][]string //[["tablea as a","a.id=b.id","left"]] + data []string + value []interface{} + orderby string + page int + page_size int + stmt *sql.Stmt + conn *sql.DB + debug bool + dbtype string +} + +func NewQuery(t ...string) *Query { + + return &Query{ + conn: DB, + dbtype: "mysql", + } +} + +func (this *Query) Conn(conn *sql.DB) *Query { + this.conn = conn + return this +} + +func (this *Query) ConnClose() error { + return this.conn.Close() +} + +func (this *Query) Db(dbname string) *Query { + this.dbname = dbname + return this +} + +func (this *Query) Table(tablename string) *Query { + this.table = tablename + return this +} +func (this *Query) Alias(tablename string) *Query { + this.alias = tablename + return this +} + +func (this *Query) Title(title string) *Query { + this.title = title + return this +} +func (this *Query) Page(page int) *Query { + this.page = page + return this +} +func (this *Query) PageSize(page_num int) *Query { + this.page_size = page_num + return this +} + +func (this *Query) Orderby(orderby string) *Query { + this.orderby = orderby + return this +} +func (this *Query) Where(where string) *Query { + this.where = append(this.where, where) + return this +} +func (this *Query) Wheres(wheres []string) *Query { + if len(wheres) > 0 { + this.where = append(this.where, wheres...) + } + return this +} +func (this *Query) WhereOr(where string) *Query { + this.where_or = append(this.where_or, where) + return this +} +func (this *Query) Value(value interface{}) *Query { + this.value = append(this.value, value) + return this +} +func (this *Query) Values(values []interface{}) *Query { + this.value = append(this.value, values...) + return this +} +func (this *Query) Join(join []string) *Query { + this.join = append(this.join, join) + return this +} +func (this *Query) Data(data string) *Query { + this.data = append(this.data, data) + return this +} +func (this *Query) Datas(datas []string) *Query { + this.data = append(this.data, datas...) + return this +} + +func (this *Query) Debug(debug bool) *Query { + this.debug = debug + return this +} + +/* + * 清理上次查询 + */ +func (this *Query) Clean() *Query { + this.title = "" + this.where = this.where[0:0] + this.where_or = this.where_or[0:0] + this.join = this.join[0:0] + this.data = this.data[0:0] + this.value = this.value[0:0] + this.orderby = "" + this.page = 0 + this.page_size = 0 + return this +} + +// 拼查询sql +func (this *Query) QueryStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + + table := getTableName(this.dbname, this.table, this.dbtype) + + // var err error + + var sql, title string + + if this.title != "" { + title = this.title + } else { + title = "*" + } + sql = StringJoin("/*slave*/ select ", title) + + if this.alias != "" { + table = StringJoin(table, " as ", this.alias) + } + + sql = StringJoin(sql, " from ", table) + + if len(this.join) > 0 { + for _, joinitem := range this.join { + if len(joinitem) < 2 { + continue + } + if len(joinitem) == 3 { + sql = StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0], this.dbtype), " on ", joinitem[1]) + } else { //默认左连接 + sql = StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0], this.dbtype), " on ", joinitem[1]) + } + } + } + if len(this.where) > 0 || len(this.where_or) > 0 { + sql = StringJoin(sql, " where ") + } + if len(this.where) > 0 { + sql = StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ") + } + if len(this.where_or) > 0 { + if len(this.where) > 0 { + sql = StringJoin(sql, " or ", strings.Join(this.where_or, " or ")) + } else { + sql = StringJoin(sql, strings.Join(this.where_or, " or ")) + } + } + + if this.orderby != "" { + sql = StringJoin(sql, " order by ", this.orderby) + } + + if this.page > 0 || this.page_size > 0 { + + if this.page < 1 { + this.page = 1 + } + if this.page_size < 1 { + this.page_size = 10 + } + from := strconv.Itoa((this.page - 1) * this.page_size) + offset := strconv.Itoa(this.page_size) + if from != "" && offset != "" { + sql = StringJoin(sql, " limit ", from, " , ", offset) + } + } + if this.debug { + log.Println("query sql:", sql, this.value) + } + condition_len := 0 //所有条件数 + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + if this.conn == nil { + this.conn = DB + } + + stmt, err = this.conn.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼更新sql +func (this *Query) UpdateStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + if len(this.where) < 1 { + return errors.New("参数错误,缺少条件") + } + + dbName := getTableName(this.dbname, this.table, this.dbtype) + + var sql string + + sql = StringJoin("update ", dbName, " set ", strings.Join(this.data, " , ")) + + sql = StringJoin(sql, " where ", strings.Join(this.where, " and ")) + + if this.debug { + log.Println("update sql:", sql, this.value) + } + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + if this.conn == nil { + this.conn = DB + } + + stmt, err = this.conn.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼插入sql +func (this *Query) CreateStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + + dbName := getTableName(this.dbname, this.table, this.dbtype) + + var sql string + + sql = StringJoin("insert into ", dbName, " set ", strings.Join(this.data, " , ")) + + if this.debug { + log.Println("insert sql:", sql, this.value) + } + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + if this.conn == nil { + this.conn = DB + } + + stmt, err = this.conn.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼删除sql +func (this *Query) DeleteStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + if len(this.where) < 1 { + return errors.New("参数错误,缺少条件") + } + + dbName := getTableName(this.dbname, this.table, this.dbtype) + + var sql string + + sql = StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and ")) + + if this.page_size > 0 { + sql = StringJoin(sql, " limit ", strconv.Itoa(this.page_size)) + } + + if this.debug { + log.Println("delete sql:", sql, this.value) + } + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + if this.conn == nil { + this.conn = DB + } + + stmt, err = this.conn.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +/** + * 执行查询列表 + * return list error + */ +func (this *Query) Select() ([]map[string]string, error) { + + conn, err := connectDb(dbhost_slaver, dbuser_slaver, dbpwd_slaver, dbname_slaver, dbport_slaver, 1, 0) + + if err != nil { + log.Println("new query error:", err) + } + if conn == nil { + log.Println("Err: no conn") + } + + _, rows, err := FetchRows(conn, this.dbname, this.table, this.alias, this.title, this.join, + this.where, this.where_or, this.value, this.orderby, this.page, this.page_size, this.debug) + + conn.Close() + + return rows, err +} + +/** + * 执行查询多条数据 + * return row error + * 2022/01/05 + */ +func (this *Query) List() ([]map[string]string, error) { + + err := this.QueryStmt() + if err != nil { + return []map[string]string{}, err + } + + if this.stmt == nil { + return []map[string]string{}, errors.New("缺少必要参数") + } + + list, err := StmtForQueryList(this.stmt, this.value) + + return list, err +} + +/** + * 执行查询一条数据 + * return row error + */ +func (this *Query) Find() (map[string]string, error) { + conn, err := connectDb(dbhost_slaver, dbuser_slaver, dbpwd_slaver, dbname_slaver, dbport_slaver, 1, 0) + + if err != nil { + log.Println("new query error:", err) + } + if conn == nil { + log.Println("Err: no conn") + } + + _, row, err := GetRow(conn, this.dbname, this.table, this.alias, this.title, this.join, + this.where, this.where_or, this.value, this.orderby, this.debug) + + conn.Close() + + return row, err +} + +/** + * 执行查询一条数据 + * return row error + * 2022/01/05 + */ +func (this *Query) Get() (map[string]string, error) { + this.page = 1 + this.page_size = 1 + err := this.QueryStmt() + if err != nil { + return map[string]string{}, err + } + + if this.stmt == nil { + return nil, errors.New("缺少必要参数") + } + row, err := StmtForQueryRow(this.stmt, this.value) + return row, err +} + +/** + * 执行更新 + * return is_updated error + */ +func (this *Query) Update() (int64, error) { + + err := this.UpdateStmt() + if err != nil { + return 0, err + } + + ret, err := StmtForUpdateExec(this.stmt, this.value) + return ret, err +} + +/** + * 执行删除 + * return is_delete error + */ +func (this *Query) Delete() (int64, error) { + + err := this.DeleteStmt() + if err != nil { + return 0, err + } + + ret, err := StmtForUpdateExec(this.stmt, this.value) + return ret, err +} + +/** + * 执行写入 + * return is_insert error + */ +func (this *Query) Create() (int64, error) { + + err := this.CreateStmt() + if err != nil { + return 0, err + } + + ret, err := StmtForInsertExec(this.stmt, this.value) + return ret, err +} diff --git a/tencentdb/chain_test.go b/tencentdb/chain_test.go new file mode 100644 index 0000000..69258c3 --- /dev/null +++ b/tencentdb/chain_test.go @@ -0,0 +1,21 @@ +package tencentdb + +import ( + "testing" +) + +func Test_Chain(t *testing.T) { + ConnectSlaver("106.52.13.101", "yueheng_slaver", "yhslave^%*345Sr", "shop_test", "13306") + + for i := 0; i < 10000; i++ { + t.Log("i:", i) + ret, err := NewQuery().Db("shop_test").Table("ttl_order_product").Alias("op"). + Join([]string{"ttl_product as p", "op.product_id=p.id"}). + Title("op.id,op.order_price,p.thumb").WhereOr("op.id =?").WhereOr("op.id = ?").Value(63).Value(64).Debug(true).Select() + + t.Log(len(ret)) + // t.Log(ret) + t.Log(err) + } + +} diff --git a/tencentdb/conn.go b/tencentdb/conn.go new file mode 100755 index 0000000..31cc1df --- /dev/null +++ b/tencentdb/conn.go @@ -0,0 +1,187 @@ +package tencentdb + +import ( + "database/sql" + "log" + + "errors" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" +) + +var DB *sql.DB + +var dbhost_slaver, dbname_slaver, dbport_slaver, dbuser_slaver, dbpwd_slaver string //从库信息 + +var use_slaver bool = false + +func Connect(DBHOST, DBUSER, DBPWD, DBNAME, DBPORT string, conns ...int) error { + + log.Println("database connectting...") + var dbConnErr error + if DBHOST != "" && DBUSER != "" && DBPWD != "" && DBPORT != "" { //&& DBNAME != "" + + for i := 0; i < 10; i++ { + DB, dbConnErr = sql.Open("mysql", DBUSER+":"+DBPWD+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8mb4") + if dbConnErr != nil { + log.Println("ERROR", "can not connect to Database, ", dbConnErr) + time.Sleep(time.Second * 5) + } else { + if len(conns) > 0 { + DB.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制 + } else { + DB.SetMaxOpenConns(200) //默认值为0表示不限制 + } + if len(conns) > 1 { + DB.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数 + } else { + DB.SetMaxIdleConns(50) + } + + DB.Ping() + + log.Println("database connected") + DB.SetConnMaxLifetime(time.Minute * 2) + break + } + } + } else { + return errors.New("db connection params errors") + } + return dbConnErr +} + +func CloseConn() error { + return DB.Close() +} + +func ConnectSlaver(DBHOST, DBUSER_SLAVER, DBPWD_SLAVER, DBNAME, DBPORT string, conns ...int) { + + dbhost_slaver = DBHOST + dbuser_slaver = DBUSER_SLAVER + dbpwd_slaver = DBPWD_SLAVER + dbname_slaver = DBNAME + dbport_slaver = DBPORT + + use_slaver = true + + // log.Println("database connectting with slaver...") + // var dbConnErr error + // if DBHOST != "" && DBUSER_SLAVER != "" && DBPWD_SLAVER != "" && DBPORT != "" { //&& DBNAME != "" + + // for i := 0; i < 10; i++ { + // SLAVER_DB, dbConnErr = sql.Open("mysql", DBUSER_SLAVER+":"+DBPWD_SLAVER+"@tcp("+DBHOST+":"+DBPORT+")/"+DBNAME+"?charset=utf8mb4") + // if dbConnErr != nil { + // log.Println("ERROR", "can not connect to Database, ", dbConnErr) + // time.Sleep(time.Second * 5) + // } else { + // if len(conns) > 0 { + // SLAVER_DB.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制 + // } else { + // SLAVER_DB.SetMaxOpenConns(200) //默认值为0表示不限制 + // } + // if len(conns) > 1 { + // SLAVER_DB.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数 + // } else { + // SLAVER_DB.SetMaxIdleConns(50) + // } + + // SLAVER_DB.Ping() + + // log.Println("database connected") + // SLAVER_DB.SetConnMaxLifetime(time.Minute * 2) + // break + // } + // } + // } else { + // return errors.New("db connection params errors") + // } + // return dbConnErr +} + +func connectDb(dbhost, dbuser, dbpwd, dbname, dbport string, conns ...int) (*sql.DB, error) { + + log.Println("database connectting...") + var dbconn *sql.DB + var dbConnErr error + if dbhost != "" && dbuser != "" && dbpwd != "" && dbport != "" { + + for i := 0; i < 10; i++ { + dbconn, dbConnErr = sql.Open("mysql", dbuser+":"+dbpwd+"@tcp("+dbhost+":"+dbport+")/"+dbname+"?charset=utf8mb4") + if dbConnErr != nil { + log.Println("ERROR", "can not connect to Database, ", dbConnErr) + time.Sleep(time.Second * 5) + } else { + if len(conns) > 0 { + dbconn.SetMaxOpenConns(conns[0]) //用于设置最大打开的连接数,默认值为0表示不限制 + } else { + dbconn.SetMaxOpenConns(200) //默认值为0表示不限制 + } + if len(conns) > 1 { + dbconn.SetMaxIdleConns(conns[1]) //用于设置闲置的连接数 + } else { + dbconn.SetMaxIdleConns(50) + } + + // dbconn.Ping() + // log.Println(dbconn.Stats()) + + log.Println("database connected") + dbconn.SetConnMaxLifetime(time.Minute * 1) + break + } + } + } else { + return nil, errors.New("db connection params errors") + } + return dbconn, dbConnErr +} + +// func CloseSlaverConn() error { +// return SLAVER_DB.Close() +// } + +/** + * 检测表名 + */ +func getTableName(dbName, table string, dbtype ...string) string { + + var db_type string = "mysql" + + if len(dbtype) > 0 { + if dbtype[0] != "" { + db_type = dbtype[0] + } + } + + var ret string + + switch db_type { + + case "mysql": + + if strings.Contains(table, ".") { + ret = table + } + if dbName != "" { + ret = StringJoin(dbName, ".", table) + } else { + ret = table + } + + case "mssql": + ret = StringJoin(dbName, ".", table) + + } + return ret +} + +func GetDbTableName(dbName, table string) string { + return getTableName(dbName, table) +} + +func judg() []string { + return []string{"=", ">", "<", "!=", "<=", ">="} +} diff --git a/tencentdb/db.go b/tencentdb/db.go new file mode 100644 index 0000000..2083191 --- /dev/null +++ b/tencentdb/db.go @@ -0,0 +1,905 @@ +package tencentdb + +import ( + "database/sql" + "log" + "strconv" + + "errors" + "strings" + "time" + + _ "github.com/go-sql-driver/mysql" +) + +/** + * 创建数据 + */ +func Insert(dbName, table string, data map[string]string) (int64, error) { + var insertId int64 + var err error + if dbName == "" && table == "" { + return insertId, errors.New("没有数据表") + } + dbName = getTableName(dbName, table) + + if len(data) < 1 { + return insertId, errors.New("没有要写入的数据") + } + keyList := make([]string, len(data)) + keyStr := make([]string, len(data)) + valueList := make([]interface{}, len(data)) + + var i int = 0 + + for key, value := range data { + keyList[i] = key + keyStr[i] = "?" + valueList[i] = value + i++ + } + + result, err := DB.Exec("insert into "+dbName+" ("+strings.Join(keyList, ",")+") value("+strings.Join(keyStr, ",")+")", valueList...) + + if err != nil { + log.Println("ERROR|插入", dbName, "数据失败,", err) + return insertId, err + } else { + insertId, _ = result.LastInsertId() + time.Sleep(time.Second * 2) + return insertId, nil + } + +} + +/** + * 修改数据 + */ +func Update(dbName, table string, data map[string]string, where map[string]string) (int64, error) { + var rowsAffected int64 + var err error + if dbName == "" && table == "" { + return rowsAffected, errors.New("没有数据表") + } + + dbName = getTableName(dbName, table) + if len(data) < 1 { + return rowsAffected, errors.New("同有更新的数据") + } + if len(where) < 1 { + return rowsAffected, errors.New("没有更新条件") + } + + keyList := make([]string, len(data)) + valueList := make([]interface{}, len(data), len(data)+len(where)) + + whereStr := make([]string, len(where)) + + var i int = 0 + + empty := false + + for key, value := range data { + keyList[i] = key + "=?" + valueList[i] = value + i++ + } + i = 0 + for key, value := range where { + if value == "" { + empty = true + break + } + whereStr[i] = key + "=?" + valueList = append(valueList, value) + i++ + } + + if empty { + log.Println("ERROR|修改数据表", dbName, "时条件中有空数据,条件:", where, "数据:", data) + return rowsAffected, errors.New("条件中有空数据") + } + result, err := DB.Exec("update "+dbName+" set "+strings.Join(keyList, " , ")+" where "+strings.Join(whereStr, " and "), valueList...) + + if err != nil { + log.Println("ERROR|修改", dbName, "数据失败,", err) + return rowsAffected, err + } else { + rowsAffected, _ = result.RowsAffected() + return rowsAffected, nil + } + +} + +/** + * 删除数据 + * @param count 删除数量 + */ +func Delete(dbName, table string, data map[string]string, del_count ...string) (int64, error) { + var count int64 + var err error + if dbName == "" && table == "" { + return count, errors.New("没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(data) < 1 { + return count, errors.New("没有要删除的数据") + } + keyList := make([]string, len(data)) + valueList := make([]interface{}, len(data)) + + var i int = 0 + + empty := false + for key, value := range data { + if value == "" { + empty = true + break + } + keyList[i] = key + "=?" + valueList[i] = value + i++ + } + + if empty { + log.Println("ERROR|删除数据表", dbName, "时条件中有空数据,条件:", data) + return count, errors.New("条件中有空数据") + } + + var limitStr string = "" + + if len(del_count) > 0 { + limitStr = " limit " + del_count[0] + + } + result, err := DB.Exec("delete from "+dbName+" where "+strings.Join(keyList, " and ")+limitStr, valueList...) + + if err != nil { + log.Println("ERROR|删除", dbName, "数据失败,", err) + return count, err + } else { + count, _ = result.RowsAffected() + return count, nil + } + +} + +/** + * 查找一条记录 + * @param dbName 数据表名 + * @param title 查询字段名 + */ +func GetData(dbName, table string, title string, where map[string]string, limit map[string]string) (int, map[string]string, error) { + var count int = 0 + info := make(map[string]string) + + if dbName == "" && table == "" { + return count, info, errors.New("没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(title) < 1 { + return count, info, errors.New("没有指定查询内容") + } + + var limitStr string = "" + + if limit != nil && len(limit) > 0 { + var from string = "0" //开始 + + if _, ok := limit["order"]; ok { + limitStr += " order by " + limit["order"] + } + + if _, ok := limit["from"]; ok { + from = limit["from"] + } + limitStr += " limit " + from + ",1" + + } else { + limitStr = " limit 1" + } + if len(where) < 1 { + return count, info, errors.New("Query condition is empty") + } + keyList := make([]string, len(where)) + valueList := make([]interface{}, len(where)) + + var i int = 0 + + empty := false + for key, value := range where { + if value == "" { + empty = true + break + } + keyList[i] = key + " = ? " + valueList[i] = value + i++ + } + + if empty { + return count, info, errors.New("Query condition is empty") + } + var rows *sql.Rows + var err error + var queryNum int = 0 + for queryNum < 3 { //如发生错误,继续查询3次,防止数据库连接断开问题 + + rows, err = DB.Query("SELECT "+title+" FROM "+dbName+" where "+strings.Join(keyList, " and ")+" "+limitStr, valueList...) + + if err == nil { + break + } else { + log.Println("ERROR", "Query from", dbName, "failed,", err, "| SELECT "+title+" FROM "+dbName+" where "+strings.Join(keyList, " and ")+" "+limitStr) + + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + defer rows.Close() + if err != nil { + return count, info, err + } + + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + + for i := range values { + scanArgs[i] = &values[i] + } + + var index string + var rowerr error + for rows.Next() { + rowerr = rows.Scan(scanArgs...) + if rowerr == nil { + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + info[index] = ToString(col) + } + } + count++ + } else { + log.Println("ERROR", "rows scan error", rowerr, dbName, keyList, valueList) + } + } + if rowerr != nil { + return count, info, rowerr + } + return count, info, nil + +} + +/** + * 查找一条记录 + * @param dbName 数据表名 + * @param title 查询字段名 + */ +func GetRow(dbconn *sql.DB, dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby string, debug bool) (int, map[string]string, error) { + var count int = 0 + info := make(map[string]string) + + if dbName == "" && table_name == "" { + return count, info, errors.New("没有数据表") + } + + table := getTableName(dbName, table_name) + + var sql_str, title string + + if titles != "" { + title = titles + } else { + title = "*" + } + sql_str = StringJoin("/*slave*/ select ", title) + + if alias != "" { + table = StringJoin(table, " as ", alias) + } + + sql_str = StringJoin(sql_str, " from ", table) + + if len(join) > 0 { + for _, joinitem := range join { + if len(joinitem) < 2 { + continue + } + if len(joinitem) == 3 { + sql_str = StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1]) + } else { //默认左连接 + sql_str = StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1]) + } + } + } + if len(where) > 0 || len(where_or) > 0 { + sql_str = StringJoin(sql_str, " where ") + } + if len(where) > 0 { + sql_str = StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ") + } + if len(where_or) > 0 { + if len(where) > 0 { + sql_str = StringJoin(sql_str, " or ", strings.Join(where_or, " or ")) + } else { + sql_str = StringJoin(sql_str, strings.Join(where_or, " or ")) + } + } + + if orderby != "" { + sql_str = StringJoin(sql_str, " order by ", orderby) + } + + if debug { + log.Println("query sql:", sql_str, valueList) + } + condition_len := 0 //所有条件数 + for _, ch2 := range sql_str { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(valueList) { + return 0, nil, errors.New("参数错误,条件值错误") + } + + var rows *sql.Rows + var err error + var queryNum int = 0 + + sql_str = StringJoin(sql_str, " limit 1") + + for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题 + + rows, err = dbconn.Query(sql_str, valueList...) + + if err == nil { + break + } else { + log.Println(err) + + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + if err != nil { + rows.Close() + return count, info, err + } + + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + + for i := range values { + scanArgs[i] = &values[i] + } + + var index string + var rowerr error + for rows.Next() { + rowerr = rows.Scan(scanArgs...) + if rowerr == nil { + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + info[index] = ToString(col) + } + } + count++ + } else { + log.Println("ERROR", rowerr) + } + } + rows.Close() + if rowerr != nil { + return count, info, rowerr + } + return count, info, nil + +} + +/** + * 查找多条记录 + * @param dbName 数据表名 + * @param title 查询字段名 + */ +func FetchRows(dbconn *sql.DB, dbName, table_name, alias string, titles string, join [][]string, where, where_or []string, valueList []interface{}, orderby string, page int, page_size int, debug bool) (int, []map[string]string, error) { + var count int = 0 + list := make([]map[string]string, 0) + + if dbName == "" && table_name == "" { + return count, list, errors.New("没有数据表") + } + + table := getTableName(dbName, table_name) + + var sql_str, title string + + if titles != "" { + title = titles + } else { + title = "*" + } + sql_str = StringJoin("/*slave*/ select ", title) + + if alias != "" { + table = StringJoin(table, " as ", alias) + } + + sql_str = StringJoin(sql_str, " from ", table) + + if len(join) > 0 { + for _, joinitem := range join { + if len(joinitem) < 2 { + continue + } + if len(joinitem) == 3 { + sql_str = StringJoin(sql_str, " ", joinitem[2], " join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1]) + } else { //默认左连接 + sql_str = StringJoin(sql_str, " left join ", getTableName(dbName, joinitem[0]), " on ", joinitem[1]) + } + } + } + + if len(where) > 0 || len(where_or) > 0 { + sql_str = StringJoin(sql_str, " where ") + } + if len(where) > 0 { + sql_str = StringJoin(sql_str, " (", strings.Join(where, " and "), " ) ") + } + if len(where_or) > 0 { + if len(where) > 0 { + sql_str = StringJoin(sql_str, " or ", strings.Join(where_or, " or ")) + } else { + sql_str = StringJoin(sql_str, strings.Join(where_or, " or ")) + } + } + + if orderby != "" { + sql_str = StringJoin(sql_str, " order by ", orderby) + } + + if page > 0 || page_size > 0 { + + if page < 1 { + page = 1 + } + if page_size < 1 { + page_size = 10 + } + from := strconv.Itoa((page - 1) * page_size) + offset := strconv.Itoa(page_size) + if from != "" && offset != "" { + sql_str = StringJoin(sql_str, " limit ", from, " , ", offset) + } + } + if debug { + log.Println("query sql:", sql_str, valueList) + } + condition_len := 0 //所有条件数 + for _, ch2 := range sql_str { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(valueList) { + return 0, list, errors.New("参数错误,条件值错误") + } + + var rows *sql.Rows + var err error + var queryNum int = 0 + for queryNum < 2 { //如发生错误,继续查询2次,防止数据库连接断开问题 + + rows, err = dbconn.Query(sql_str, valueList...) + + if err == nil { + break + } else { + log.Println(err) + + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + if err != nil { + rows.Close() + return 0, list, err + } + + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + + for i := range values { + scanArgs[i] = &values[i] + } + + var index string + var rowerr error + var info map[string]string + + for rows.Next() { + rowerr = rows.Scan(scanArgs...) + info = make(map[string]string) + if rowerr == nil { + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + info[index] = ToString(col) + } + } + count++ + } else { + log.Println("ERROR", rowerr) + } + if len(info) > 0 { + list = append(list, info) + } + } + + rows.Close() + return count, list, nil + +} + +func GetInfo(dbName, table string, title string, where map[string]string) (map[string]string, error) { + + count, info, gzErr := GetData(dbName, table, title, where, nil) + if gzErr != nil { + return info, gzErr + } else { + if count < 1 { + return info, errors.New("No data") + } + return info, nil + } + +} + +/** + * 查询列表 + * 2018/04/19 + */ +func GetList(dbName, table string, title string, where map[string]string, limit map[string]string) ([]map[string]string, error) { + + var list []map[string]string + if dbName == "" && table == "" { + return list, errors.New("没有数据表") + } + + dbName = getTableName(dbName, table) + + var rows *sql.Rows + var err error + var queryNum int = 0 + + var limitStr string = "" + + if len(limit) > 0 { + + var offset string = "0" //偏移量,个数 + var from string = "" //开始 + + if _, ok := limit["order"]; ok { + limitStr += " order by " + limit["order"] + } + + if _, ok := limit["offset"]; ok { + offset = limit["offset"] + } + if _, ok := limit["from"]; ok { + from = limit["from"] + } + if offset != "0" && from != "" { + limitStr += " limit " + from + "," + offset + } + } + + if len(where) > 0 { + valueList := make([]interface{}, len(where)) + whereStr := make([]string, len(where)) + i := 0 + var keys []string + for key, value := range where { + key = strings.Trim(key, " ") + value = strings.Trim(value, " ") + if value == "" || key == "" { + continue + // return list, errors.New("Query condition is empty") + } + if strings.Contains(key, " ") { + //key中包含空格,判断是否不等于条件 + keys = strings.Split(key, " ") + if IsInStringArray(judg(), strings.Trim(keys[1], " ")) { + whereStr[i] = strings.Trim(keys[0], " ") + " " + strings.Trim(keys[1], " ") + " ?" + } + } else { + whereStr[i] = key + " = ?" + valueList[i] = value + } + i++ + } + + if len(whereStr) == 0 || len(valueList) == 0 { + return list, errors.New("Query condition is empty") + } + + for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题 + + rows, err = DB.Query("select "+title+" from "+dbName+" where "+strings.Join(whereStr, " and ")+" "+limitStr, valueList...) + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + } else { + for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题 + + rows, err = DB.Query("select " + title + " from " + dbName + " " + limitStr) + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + } + + if err != nil { + return list, err + } + defer rows.Close() + + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + for i := range values { + scanArgs[i] = &values[i] + } + + var record map[string]string + var index string + for rows.Next() { + //将行数据保存到record字典 + err = rows.Scan(scanArgs...) + record = make(map[string]string) + + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + record[index] = ToString(col) + } + } + list = append(list, record) + } + + return list, nil +} + +/** + * 查询总数 + * 2018/04/19 + */ +func GetTotal(dbName, table string, args ...string) (total int) { + + if dbName == "" && table == "" { + return + } + + dbName = getTableName(dbName, table) + + var title string = "*" + + if len(args) > 0 { + title = args[0] + } + + var rows *sql.Rows + var err error + var queryNum int = 0 + + for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题 + + rows, err = DB.Query("select count(" + title + ") as count from " + dbName + " limit 1") + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + if err != nil { + log.Println("ERROR|get", dbName, "total error", err) + return + } + defer rows.Close() + + var count int + + for rows.Next() { + //将行数据保存到record字典 + err = rows.Scan(&count) + if err != nil { + log.Println("ERROR|get", dbName, "total error", err) + } else { + total = count + } + } + + return +} + +/** + * 查询总数 + * 2020/06/04 + */ +func GetCount(dbName, table string, where map[string]string, args ...string) (total int) { + + if dbName == "" && table == "" { + return + } + dbName = getTableName(dbName, table) + + var title string = "*" + + if len(title) > 0 { + title = args[0] + } + + var rows *sql.Rows + var err error + var queryNum int = 0 + + if len(where) > 0 { + valueList := make([]interface{}, len(where)) + whereStr := make([]string, len(where)) + i := 0 + var keys []string + for key, value := range where { + key = strings.Trim(key, " ") + value = strings.Trim(value, " ") + if value == "" || key == "" { + continue + // return list, errors.New("Query condition is empty") + } + if strings.Contains(key, " ") { + //key中包含空格,判断是否不等于条件 + keys = strings.Split(key, " ") + if IsInStringArray(judg(), strings.Trim(keys[1], " ")) { + whereStr[i] = strings.Trim(keys[0], " ") + " " + strings.Trim(keys[1], " ") + " ?" + } + } else { + whereStr[i] = key + " = ?" + valueList[i] = value + } + i++ + } + + for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题 + + rows, err = DB.Query("select count("+title+") as count from "+dbName+" where "+strings.Join(whereStr, " and ")+" limit 1", valueList...) + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + } else { + for queryNum < 5 { //如发生错误,继续查询5次,防止数据库连接断开问题 + + rows, err = DB.Query("select count(" + title + ") as count from " + dbName + " limit 1") + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + } + + if err != nil { + log.Println("ERROR|get", dbName, "count error", err) + return + } + defer rows.Close() + + var count int + + for rows.Next() { + //将行数据保存到record字典 + err = rows.Scan(&count) + if err != nil { + log.Println("ERROR|get", dbName, "count error", err) + } else { + total = count + } + } + + return +} +func DoQuery(args ...interface{}) ([]map[string]string, error) { + var list []map[string]string + if len(args) < 1 { + return list, errors.New("Query condition is empty") + } + queryStr := ToString(args[0]) + if queryStr == "" { + return list, errors.New("Query condition is empty") + } + var rows *sql.Rows + var err error + var queryNum int = 0 + + for queryNum < 3 { //如发生错误,继续查询5次,防止数据库连接断开问题 + if len(args) > 1 { + rows, err = DB.Query(queryStr, args[1:]...) //strings.Join(args[1:], ",") + if err != nil { + log.Println("ERROR|DoQuery error:", err) + } + } else { + rows, err = DB.Query(queryStr) + if err != nil { + log.Println("ERROR|DoQuery error:", err) + } + } + + if err == nil { + break + } else { + time.Sleep(time.Millisecond * 500) + } + queryNum++ + } + + if err != nil { + return list, err + } + defer rows.Close() + + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + for i := range values { + scanArgs[i] = &values[i] + } + + var record map[string]string + var index string + for rows.Next() { + //将行数据保存到record字典 + err = rows.Scan(scanArgs...) + record = make(map[string]string) + + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + record[index] = ToString(col) + } + } + list = append(list, record) + } + + return list, nil +} diff --git a/tencentdb/db_test.go b/tencentdb/db_test.go new file mode 100755 index 0000000..94a9c0c --- /dev/null +++ b/tencentdb/db_test.go @@ -0,0 +1,51 @@ +package tencentdb + +import ( + "log" + "testing" +) + +func Test_Connet(t *testing.T) { + //go func() { + for i := 0; i < 1; i++ { + dbhost := "localhost" + dbname := "shop" + dbusername := "tetele" + dbpassword := "fly123456" + dbport := "3306" + table := "ttl_order_product" + err := Connect(dbhost, dbusername, dbpassword, dbname, dbport) + + if err != nil { + log.Println(err.Error()) + } + + //_,err = new(Query).Db(dbname).Table("ttl_user").Where("id > 0").Select() + + // _, err = new(Query).Db(dbname).Table("ttl_news"). + // Datas([]string{"title=?", "content=?"}). + // Values([]interface{}{"aaaaaaaaa", "bbbbbb"}).Create() + + title := "op.id,op.sn,op.order_price" + alias := "op" + join := [][]string{} + join = append(join, []string{"ttl_product as p", "op.product_id=p.id"}) + where := []string{} + where_or := []string{} + valueList := []interface{}{} + orderby := "id desc" + debug := true + + // count, row, err := GetRow(dbname, table, alias, title, join, where, where_or, valueList, orderby, debug) + count, row, err := FetchRows(dbname, table, alias, title, join, where, where_or, valueList, orderby, 1, 10, debug) + + log.Println(count) + log.Println(row) + log.Println(err) + if err != nil { + log.Println(err.Error()) + } + } + //}() + +} diff --git a/tencentdb/go.mod b/tencentdb/go.mod new file mode 100644 index 0000000..ef8129c --- /dev/null +++ b/tencentdb/go.mod @@ -0,0 +1,7 @@ +module git.tetele.net/mysql/tencentdb + +go 1.16 + +require ( + github.com/go-sql-driver/mysql v1.5.0 +) diff --git a/tencentdb/go.sum b/tencentdb/go.sum new file mode 100644 index 0000000..adffb88 --- /dev/null +++ b/tencentdb/go.sum @@ -0,0 +1,11 @@ +git.tetele.net/tgo/helper v0.1.0 h1:ZdsBXUWX3+22ZzHTZRldBfBsQwu+CwUH8qScUvpgimE= +git.tetele.net/tgo/helper v0.1.0/go.mod h1:shYQE/hvMy3fOE8JXKGxvywOXiz3M5Nw4e+u7HR8+NY= +github.com/denisenkom/go-mssqldb v0.11.0 h1:9rHa233rhdOyrz2GcP9NM+gi2psgJZ4GWDpL/7ND8HI= +github.com/denisenkom/go-mssqldb v0.11.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/go-sql-driver/mysql v1.5.0 h1:ozyZYNQW3x3HtqT1jira07DN2PArx2v7/mN66gGcHOs= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= +github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c h1:Vj5n4GlwjmQteupaxJ9+0FNOmBrHfq7vN4btdGoDZgI= +golang.org/x/crypto v0.0.0-20190325154230-a5d413f7728c/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= diff --git a/tencentdb/prepare.go b/tencentdb/prepare.go new file mode 100755 index 0000000..b68cf17 --- /dev/null +++ b/tencentdb/prepare.go @@ -0,0 +1,456 @@ +package tencentdb + +import ( + "database/sql" + "errors" + "log" + "strings" +) + +/** + * 准备查询 + * return Stmt error + */ +func StmtForRead(dbName, table string, title string, where []string, limit map[string]string) (*sql.Stmt, error) { + + if dbName == "" && table == "" { + return nil, errors.New("参数错误,没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(title) < 1 { + return nil, errors.New("没有要查询内容") + } + + var limitStr string = "" + + if limit != nil && len(limit) > 0 { + var from, offset string = "", "" //开始 + + if _, ok := limit["order"]; ok { + limitStr += " order by " + limit["order"] + } + + if _, ok := limit["from"]; ok { + from = limit["from"] + } + if _, ok := limit["offset"]; ok { + offset = limit["offset"] + } + if from != "" && offset != "" { + + limitStr += " limit " + from + "," + offset + } + + } + + var stmt *sql.Stmt + var err error + + if len(where) > 0 { + // log.Println("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + limitStr) + stmt, err = DB.Prepare("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + limitStr) + } else { + // log.Println("SELECT " + title + " FROM " + dbName + limitStr) + stmt, err = DB.Prepare("SELECT " + title + " FROM " + dbName + limitStr) + } + + return stmt, err +} + +func CloseStmt(stmt *sql.Stmt) error { + return stmt.Close() +} + +/** + * 执行查询列表 + * return list error + */ +func StmtForQueryList(stmt *sql.Stmt, valuelist []interface{}) ([]map[string]string, error) { + + if stmt == nil { + return nil, errors.New("缺少必要参数") + } + + // log.Println(valuelist...) + + rows, err := stmt.Query(valuelist...) + defer stmt.Close() + if err != nil { + if stmt != nil { + stmt.Close() + } + return nil, err + } + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + + for i := range values { + scanArgs[i] = &values[i] + } + + var list []map[string]string + var index string + var rowerr error + info := make(map[string]string) + + for rows.Next() { + + rowerr = rows.Scan(scanArgs...) + + info = make(map[string]string) + if rowerr == nil { + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + info[index] = ToString(col) + } + } + } else { + log.Println("rows scan error", rowerr) + } + if len(info) > 0 { + list = append(list, info) + } + } + + return list, nil +} + +/** + * 执行查询一条数据 + * return row error + */ +func StmtForQueryRow(stmt *sql.Stmt, valuelist []interface{}) (map[string]string, error) { + + if stmt == nil || len(valuelist) < 1 { + return nil, errors.New("缺少必要参数") + } + rows, err := stmt.Query(valuelist...) + defer stmt.Close() + if err != nil { + if stmt != nil { + stmt.Close() + } + return nil, err + } + columns, _ := rows.Columns() + scanArgs := make([]interface{}, len(columns)) + values := make([]interface{}, len(columns)) + + for i := range values { + scanArgs[i] = &values[i] + } + + var index string + var rowerr error + info := make(map[string]string) + for rows.Next() { + rowerr = rows.Scan(scanArgs...) + if rowerr == nil { + for i, col := range values { + if col != nil { + index = StrFirstToUpper(columns[i]) + info[index] = ToString(col) + } + } + } else { + log.Println("rows scan error", rowerr) + } + } + if rowerr != nil { + return info, errors.New("数据出错") + } + return info, nil +} + +/** + * 准备更新 + * return Stmt error + */ +func StmtForUpdate(dbName, table string, data []string, where []string) (*sql.Stmt, error) { + + if dbName == "" && table == "" { + return nil, errors.New("参数错误,没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(where) < 1 { + return nil, errors.New("参数错误,没有更新条件") + } + + var stmt *sql.Stmt + var err error + + stmt, err = DB.Prepare("update " + dbName + " set " + strings.Join(data, " , ") + " where " + strings.Join(where, " and ")) + + return stmt, err +} + +/** + * 执行更新 + * return is_updated error + */ +func StmtForUpdateExec(stmt *sql.Stmt, valuelist []interface{}) (int64, error) { + res, err := stmt.Exec(valuelist...) + if err != nil { + return 0, errors.New("更新失败:" + err.Error()) + } + + return res.RowsAffected() +} + +/** + * 准备写入 + * return Stmt error + */ +func StmtForInsert(dbName, table string, data []string) (*sql.Stmt, error) { + + if dbName == "" && table == "" { + return nil, errors.New("参数错误,没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(data) < 1 { + return nil, errors.New("参数错误,没有要写入的数据") + } + + var stmt *sql.Stmt + var err error + + stmt, err = DB.Prepare("insert into " + dbName + " set " + strings.Join(data, " , ")) + + return stmt, err +} + +/** + * 执行写入 + * @return lastId error + */ +func StmtForInsertExec(stmt *sql.Stmt, valuelist []interface{}) (int64, error) { + res, err := stmt.Exec(valuelist...) + if err != nil { + return 0, errors.New("创建失败:" + err.Error()) + } + return res.LastInsertId() +} + +/** + * 使用db prepare方式查询列表 + * @param dbName + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * @param page 查询范围,可传两个值 pageNum,pageSize + * GZ + * 2020/05/19 + */ +func GetListByStmt(dbName string, table string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) { + + if len(page) > 0 { + pageNum, pageSize := page[0], 10 + if len(page) > 1 { + pageSize = page[1] + } + limit["from"], limit["offset"] = GetPage(pageNum, pageSize) + } + + stmt, err := StmtForRead(dbName, table, title, where, limit) + + if err != nil { + return nil, err + } + defer stmt.Close() + + return StmtForQueryList(stmt, valuelist) + +} + +/** + * 使用db prepare方式查询单条数据 + * @param dbName + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * GZ + * 2020/05/19 + */ +func GetDataByStmt(dbName string, table string, title string, where []string, valuelist []interface{}, limit map[string]string) (map[string]string, error) { + + stmt, err := StmtForRead(dbName, table, title, where, limit) + + if err != nil { + return nil, err + } + defer stmt.Close() + + return StmtForQueryRow(stmt, valuelist) +} + +/** + * 使用db prepare修改数据 + * @param dbName + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * GZ + * 2020/05/19 + */ +func UpdateByStmt(dbName string, table string, data []string, where []string, valuelist []interface{}) (int64, error) { + + stmt, err := StmtForUpdate(dbName, table, data, where) + + if err != nil { + return 0, err + } + + defer stmt.Close() + return StmtForUpdateExec(stmt, valuelist) +} + +/** + * 使用db prepare写入数据 + * @param dbName + * @param table 表名 + * @param data 写入的字段 + * @param valuelist 写入的值 + * GZ + * 2020/08/06 + */ +func InsertByStmt(dbName string, table string, data []string, valuelist []interface{}) (int64, error) { + + stmt, err := StmtForInsert(dbName, table, data) + + if err != nil { + return 0, err + } + + defer stmt.Close() + return StmtForInsertExec(stmt, valuelist) +} + +/** + * 自定义查询 + * return Stmt error + */ +func StmtForQuery(querysql string) (*sql.Stmt, error) { + + if querysql == "" { + return nil, errors.New("参数错误,没有数据表") + } + + var stmt *sql.Stmt + var err error + + stmt, err = DB.Prepare(querysql) + + return stmt, err +} + +/** + * 执行自定义查询 + * @return lastId error + */ +func QueryByStmt(sql string, valuelist []interface{}) ([]map[string]string, error) { + stmt, err := StmtForQuery(sql) + + if err != nil { + return nil, err + } + + defer stmt.Close() + return StmtForQueryList(stmt, valuelist) + +} + +/** + * 联表查询 + * @param dbName + * @param tableA 表一 + * @param tableA_alias 表一别名 + * @param tableB 表二 + * @param tableB_alias 表二别名 + * @param join 联表方式 + * @param join_on 联表字段 + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * @param page 查询范围,可传两个值 pageNum,pageSize + * GZ + * 2020/11/23 + */ +func GetJoinListByStmt(dbName string, tableA, tableA_alias string, tableB, tableB_alias string, join_type, join_on string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) { + + if len(page) > 0 { + pageNum, pageSize := page[0], 10 + if len(page) > 1 { + pageSize = page[1] + } + limit["from"], limit["offset"] = GetPage(pageNum, pageSize) + } + + if tableA_alias != "" { + tableA = StringJoin(dbName, ".", tableA, " as ", tableA_alias) + } + + if tableB_alias != "" { + tableB = StringJoin(dbName, ".", tableB, " as ", tableB_alias) + } + table := StringJoin(tableA, " ", join_type, " join ", tableB, " on ", join_on) + stmt, err := StmtForRead(dbName, table, title, where, limit) + + if err != nil { + return nil, err + } + defer stmt.Close() + + return StmtForQueryList(stmt, valuelist) + +} + +/** + * 左联表查询 + * @param dbName + * @param tableA 表一 + * @param tableB 表二 + * @param join_on 联表字段 + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * @param page 查询范围,可传两个值 pageNum,pageSize + * GZ + * 2021/1/27 + */ +func LeftJoinListByStmt(dbName string, tableA, tableB string, join_on string, title string, where []string, valuelist []interface{}, limit map[string]string, page ...int) ([]map[string]string, error) { + + if len(page) > 0 { + pageNum, pageSize := page[0], 10 + if len(page) > 1 { + pageSize = page[1] + } + limit["from"], limit["offset"] = GetPage(pageNum, pageSize) + } + + tableA = getTableName(dbName, tableA) + tableB = getTableName(dbName, tableB) + + table := StringJoin(tableA, " left join ", tableB, " on ", join_on) + stmt, err := StmtForRead(dbName, table, title, where, limit) + + if err != nil { + return nil, err + } + defer stmt.Close() + + return StmtForQueryList(stmt, valuelist) + +} diff --git a/tencentdb/prepare_test.go b/tencentdb/prepare_test.go new file mode 100644 index 0000000..fcaca67 --- /dev/null +++ b/tencentdb/prepare_test.go @@ -0,0 +1,21 @@ +package tencentdb + +import ( + "testing" +) + +func Test_StmtForExec(t *testing.T) { + Connect("127.0.0.1", "root", "123456", "tetele_empty", "3306") + + stmt, err := StmtForUpdate("dev_tetele_net", "ttl_xshop_order", []string{"user_id = ?", "pay_time = pay_time+1"}, []string{"id=1"}) + + if err != nil { + t.Error(err) + } + + defer stmt.Close() + ret, err := StmtForUpdateExec(stmt, []interface{}{"1"}) + + t.Log(ret) + t.Log(err) +} diff --git a/tencentdb/string.go b/tencentdb/string.go new file mode 100644 index 0000000..6e672cc --- /dev/null +++ b/tencentdb/string.go @@ -0,0 +1,167 @@ +package tencentdb + +import ( + "fmt" + "log" + "strconv" + "strings" +) + +/* + * 连接多个字符串 + * 2019/05/05 + */ +func StringJoin(s ...string) string { + var build strings.Builder + if len(s) > 0 { + for _, v := range s { + build.WriteString(v) + } + } + + return build.String() +} + +/** + * 字符串转大驼峰 ios_bbbbbbbb -> IosBbbbbbbbb + */ +func StrFirstToUpper(str string) string { + str = strings.ReplaceAll(str, "`", "") + temp := strings.Split(str, "_") + var upperStr string + for y := 0; y < len(temp); y++ { + vv := []rune(temp[y]) + for i := 0; i < len(vv); i++ { + if i == 0 { + vv[i] -= 32 + upperStr += string(vv[i]) + } else { + upperStr += string(vv[i]) + } + } + } + return upperStr +} + +func ToString(v interface{}) string { + var value string + switch v.(type) { + case string: + value = v.(string) + case int: + value = strconv.Itoa(v.(int)) + case float64: + value = strconv.FormatFloat(v.(float64), 'f', 2, 64) + case float32: + value = strconv.FormatFloat(float64(v.(float32)), 'f', 2, 64) + case int64: + value = strconv.FormatInt(v.(int64), 10) + case []uint8: + value = string(v.([]uint8)) + // case []byte: + // value = string(v.([]byte)) + case interface{}: + value = v.(string) + case nil: + value = "" + default: + log.Println("参数值类型错误", v, "not in string|int|float64|interface|int64") + } + return strings.Trim(value, " ") +} + +/** + * 是否存在在字符切片中 + */ +func IsInStringArray(arr []string, str string) bool { + var isIn bool = false + length := len(arr) + if length < 1 { + return false + } + for _, item := range arr { + if item == str { + isIn = true + break + } + } + return isIn +} + +func ToInt(inter interface{}) int { + var value int + + switch inter.(type) { + + case string: + value, _ = strconv.Atoi(inter.(string)) + case int: + value = inter.(int) + case int64: + value = int(inter.(int64)) + case float64: + value, _ = strconv.Atoi(fmt.Sprintf("%1.0f", inter)) + case nil: + value = 0 + case interface{}: + value = inter.(int) + default: + log.Println("参数值类型错误", inter, "not in string|int|float64|interface|int64") + } + return value +} + +func ToInt64(inter interface{}) int64 { + var value int64 + + switch inter.(type) { + + case string: + value, _ = strconv.ParseInt(inter.(string), 10, 64) + case int: + value = int64(inter.(int)) + case int64: + value = inter.(int64) + case float64: + value_int, _ := strconv.Atoi(fmt.Sprintf("%1.0f", inter)) + value = int64(value_int) + case nil: + value = 0 + case interface{}: + if _, ok := inter.(int64); !ok { + value = inter.(int64) + } + default: + log.Println("参数值类型错误", inter, "not in string|int|float64|interface|int64") + } + return value +} + +/** + * 根据第几页计算从第几行开始 + * @param pageNum 第几页 + * @param pageSize 每页几行 + * @return from,offset 开始行数,偏移量 + * 2020/05/15 + * gz + */ +func GetPage(pageNum, pageSize interface{}) (string, string) { + + var from string + var offset int = ToInt(pageSize) + + var pageNumInt, pageSizeInt int = ToInt(pageNum), ToInt(pageSize) + + if pageNumInt < 1 { + pageNumInt = 1 + } + + if pageSizeInt < 1 { + offset = 10 + pageSizeInt = 10 + } + + from = ToString((pageNumInt - 1) * pageSizeInt) + + return from, ToString(offset) +} diff --git a/tencentdb/transaction.go b/tencentdb/transaction.go new file mode 100755 index 0000000..1153015 --- /dev/null +++ b/tencentdb/transaction.go @@ -0,0 +1,301 @@ +/** + * DB transaction + */ +package tencentdb + +import ( + "database/sql" + "errors" + "log" + "strings" + "time" +) + +/** + * 创建数据 + */ +func TxInsert(tx *sql.Tx, dbname, table string, data map[string]string) (int64, error) { + + var insertId int64 + var err error + if dbname == "" && table == "" { + return 0, errors.New("参数错误,没有数据表") + } + dbName := getTableName(dbname, table) + if len(data) < 1 { + return 0, errors.New("参数错误,没有要写入的数据") + } + + keyList := make([]string, len(data)) + keyStr := make([]string, len(data)) + valueList := make([]interface{}, len(data)) + + var i int = 0 + + for key, value := range data { + keyList[i] = key + keyStr[i] = "?" + valueList[i] = value + i++ + } + + result, err := tx.Exec("insert into "+dbName+" ("+strings.Join(keyList, ",")+") value("+strings.Join(keyStr, ",")+")", valueList...) + + if err != nil { + log.Println("ERROR", "insert into ", dbName, "error:", err) + return insertId, err + } else { + insertId, _ = result.LastInsertId() + time.Sleep(time.Second * 2) + return insertId, nil + } + +} + +/** + * 准备写入 + * return Stmt error + */ +func TxPreInsert(tx *sql.Tx, dbname, table string, data map[string]interface{}) (int64, error) { + + if dbname == "" && table == "" { + return 0, errors.New("params error,no db or table") + } + + dbName := getTableName(dbname, table) + + if len(data) < 1 { + return 0, errors.New("params error,no data to insert") + } + + var err error + + var stmt *sql.Stmt + + var field []string = make([]string, len(data)) + var valuelist []interface{} = make([]interface{}, len(data)) + + var i int = 0 + for key, item := range data { + field[i] = key + "=?" + valuelist[i] = item + i++ + } + + sql := "insert into " + dbName + " set " + strings.Join(field, " , ") + stmt, err = tx.Prepare(sql) + + if err != nil { + log.Println("insert prepare error:", sql, err) + return 0, errors.New("insert prepare error:" + err.Error()) + } + result, err := stmt.Exec(valuelist...) + if err != nil { + log.Println("insert exec error:", sql, valuelist, err) + return 0, errors.New("insert exec error:" + err.Error()) + } + insertId, _ := result.LastInsertId() + return insertId, nil + +} + +/** + * 修改数据 + */ +func TxUpdate(tx *sql.Tx, dbname, table string, data map[string]string, where map[string]string) (int64, error) { + var rowsAffected int64 + var err error + if dbname == "" && table == "" { + return rowsAffected, errors.New("参数错误,没有数据表") + } + dbName := getTableName(dbname, table) + if len(data) < 1 { + return rowsAffected, errors.New("参数错误,没有要写入的数据") + } + if len(where) < 1 { + return rowsAffected, errors.New("参数错误,没有修改条件") + } + + keyList := make([]string, len(data)) + valueList := make([]interface{}, len(data), len(data)+len(where)) + + whereStr := make([]string, len(where)) + + var i int = 0 + + empty := false + + for key, value := range data { + keyList[i] = key + "=?" + valueList[i] = value + i++ + } + i = 0 + for key, value := range where { + if value == "" { + empty = true + break + } + whereStr[i] = key + "=?" + valueList = append(valueList, value) + i++ + } + + if empty { + log.Println("ERROR", "update", dbName, "error, params empty") + return rowsAffected, errors.New("params empty") + } + result, err := tx.Exec("update "+dbName+" set "+strings.Join(keyList, " , ")+" where "+strings.Join(whereStr, " and "), valueList...) + + if err != nil { + log.Println("ERROR", "update", dbName, "error:", err) + return rowsAffected, err + } else { + rowsAffected, _ = result.RowsAffected() + return rowsAffected, nil + } + +} + +/** + * 准备更新 + * return Stmt error + */ +func TxPreUpdate(tx *sql.Tx, dbname, table string, data []string, where []string, valuelist []interface{}) (int64, error) { + + if dbname == "" && table == "" { + return 0, errors.New("params error,no db or table") + } + + dbName := getTableName(dbname, table) + + if len(where) < 1 { + return 0, errors.New("params error, no data for update") + } + + var err error + + var stmt *sql.Stmt + + sql := "update " + dbName + " set " + strings.Join(data, " , ") + " where " + strings.Join(where, " and ") + + stmt, err = tx.Prepare(sql) + + if err != nil { + log.Println("update prepare error:", sql, err) + return 0, errors.New("update prepare error:" + err.Error()) + } + res, err := stmt.Exec(valuelist...) + if err != nil { + log.Println("update exec error:", sql, valuelist, err) + return 0, errors.New("update exec error:" + err.Error()) + } + + return res.RowsAffected() +} + +/** + * 删除数据 + * @param count 删除数量 + */ +func TxDelete(tx *sql.Tx, dbname, table string, where map[string]string, del_count ...string) (int64, error) { + var count int64 + var err error + if dbname == "" && table == "" { + return count, errors.New("参数错误,没有数据表") + } + dbName := getTableName(dbname, table) + + if len(where) < 1 { + return count, errors.New("参数错误,没有删除条件") + } + keyList := make([]string, len(where)) + valueList := make([]interface{}, len(where)) + + var i int = 0 + + empty := false + for key, value := range where { + if value == "" { + empty = true + break + } + keyList[i] = key + "=?" + valueList[i] = value + i++ + } + + if empty { + log.Println("ERROR", "delete from", dbName, "error, where:", where) + return count, errors.New("params empty") + } + + var limitStr string = "" + + if len(del_count) > 0 { + limitStr = " limit " + del_count[0] + + } + result, err := tx.Exec("delete from "+dbName+" where "+strings.Join(keyList, " and ")+limitStr, valueList...) + + if err != nil { + log.Println("ERROR", "delete from", dbName, "error:", err) + return count, err + } else { + count, _ = result.RowsAffected() + return count, nil + } + +} + +/** + * 准备查询 + * return Stmt error + */ +func TxForRead(tx *sql.Tx, dbName, table string, title string, where []string) (*sql.Stmt, error) { + + if dbName == "" && table == "" { + return nil, errors.New("参数错误,没有数据表") + } + + dbName = getTableName(dbName, table) + + if len(title) < 1 { + return nil, errors.New("没有要查询内容") + } + + var stmt *sql.Stmt + var err error + + if len(where) > 0 { + // log.Println("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + " FOR UPDATE") + stmt, err = tx.Prepare("SELECT " + title + " FROM " + dbName + " where " + strings.Join(where, " and ") + " FOR UPDATE") + } else { + // log.Println("SELECT " + title + " FROM " + dbName + " FOR UPDATE") + stmt, err = tx.Prepare("SELECT " + title + " FROM " + dbName + " FOR UPDATE") + } + + return stmt, err +} + +/** + * 使用db prepare方式查询单条数据 + * @param dbName + * @param title 查询的字段名 + * @param where 查询条件 + * @param valuelist 查询的条件值 + * @param limit 查询排序 + * GZ + * 2020/05/19 + */ +func TxGetData(tx *sql.Tx, dbName string, table string, title string, where []string, valuelist []interface{}) (map[string]string, error) { + + stmt, err := TxForRead(tx, dbName, table, title, where) + + if err != nil { + return nil, err + } + defer stmt.Close() + + return StmtForQueryRow(stmt, valuelist) +} diff --git a/tencentdb/transaction_chain.go b/tencentdb/transaction_chain.go new file mode 100644 index 0000000..e383293 --- /dev/null +++ b/tencentdb/transaction_chain.go @@ -0,0 +1,451 @@ +package tencentdb + +/** + * 事务操作 + */ +import ( + "database/sql" + "errors" + "log" + "strconv" + "strings" +) + +type TxQuery struct { + dbname string + table string + alias string + title string + where []string + where_or []string + join [][]string //[["tablea as a","a.id=b.id","left"]] + data []string + value []interface{} + orderby string + page int + page_size int + stmt *sql.Stmt + conn *sql.DB + tx *sql.Tx + debug bool +} + +func NewTxQuery(t ...string) *TxQuery { + + var conn_type *sql.DB = DB + + tx, err := conn_type.Begin() + if err != nil { + log.Println("start tx begin error", err) + } + + return &TxQuery{ + conn: conn_type, + tx: tx, + } +} + +func (this *TxQuery) Conn(conn *sql.DB) *TxQuery { + this.conn = conn + return this +} +func (this *TxQuery) Db(dbname string) *TxQuery { + this.dbname = dbname + return this +} + +func (this *TxQuery) Table(tablename string) *TxQuery { + this.table = tablename + return this +} +func (this *TxQuery) Alias(tablename string) *TxQuery { + this.alias = tablename + return this +} + +func (this *TxQuery) Title(title string) *TxQuery { + this.title = title + return this +} +func (this *TxQuery) Page(page int) *TxQuery { + this.page = page + return this +} +func (this *TxQuery) PageSize(page_num int) *TxQuery { + this.page_size = page_num + return this +} + +func (this *TxQuery) Orderby(orderby string) *TxQuery { + this.orderby = orderby + return this +} +func (this *TxQuery) Where(where string) *TxQuery { + this.where = append(this.where, where) + return this +} +func (this *TxQuery) Wheres(wheres []string) *TxQuery { + if len(wheres) > 0 { + this.where = append(this.where, wheres...) + } + return this +} +func (this *TxQuery) WhereOr(where string) *TxQuery { + this.where_or = append(this.where_or, where) + return this +} +func (this *TxQuery) Value(value interface{}) *TxQuery { + this.value = append(this.value, value) + return this +} +func (this *TxQuery) Values(values []interface{}) *TxQuery { + this.value = append(this.value, values...) + return this +} +func (this *TxQuery) Join(join []string) *TxQuery { + this.join = append(this.join, join) + return this +} +func (this *TxQuery) Data(data string) *TxQuery { + this.data = append(this.data, data) + return this +} +func (this *TxQuery) Datas(datas []string) *TxQuery { + this.data = append(this.data, datas...) + return this +} +func (this *TxQuery) Debug(debug bool) *TxQuery { + this.debug = debug + return this +} + +/* + * 清理上次查询 + */ +func (this *TxQuery) Clean() *TxQuery { + this.title = "" + this.where = this.where[0:0] + this.where_or = this.where_or[0:0] + this.join = this.join[0:0] + this.data = this.data[0:0] + this.value = this.value[0:0] + this.orderby = "" + this.page = 0 + this.page_size = 0 + return this +} + +// 拼查询sql +func (this *TxQuery) QueryStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + + table := getTableName(this.dbname, this.table) + + var sql, title string + + if this.title != "" { + title = this.title + } else { + title = "*" + } + sql = StringJoin("select ", title) + + if this.alias != "" { + table = StringJoin(table, " as ", this.alias) + } + + sql = StringJoin(sql, " from ", table) + + if len(this.join) > 0 { + for _, joinitem := range this.join { + if len(joinitem) < 2 { + continue + } + if len(joinitem) == 3 { + sql = StringJoin(sql, " ", joinitem[2], " join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1]) + } else { //默认左连接 + sql = StringJoin(sql, " left join ", getTableName(this.dbname, joinitem[0]), " on ", joinitem[1]) + } + } + } + if len(this.where) > 0 || len(this.where_or) > 0 { + sql = StringJoin(sql, " where ") + } + if len(this.where) > 0 { + sql = StringJoin(sql, " (", strings.Join(this.where, " and "), " ) ") + } + if len(this.where_or) > 0 { + if len(this.where) > 0 { + sql = StringJoin(sql, " or ", strings.Join(this.where_or, " or ")) + } else { + sql = StringJoin(sql, strings.Join(this.where_or, " or ")) + } + } + + if this.orderby != "" { + sql = StringJoin(sql, " order by ", this.orderby) + } + + if this.page > 0 || this.page_size > 0 { + + if this.page < 1 { + this.page = 1 + } + if this.page_size < 1 { + this.page_size = 10 + } + from := strconv.Itoa((this.page - 1) * this.page_size) + offset := strconv.Itoa(this.page_size) + if from != "" && offset != "" { + sql = StringJoin(sql, " limit ", from, " , ", offset) + } + } + + if this.debug { + log.Println("query sql:", sql, this.value) + } + + condition_len := 0 //所有条件数 + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + stmt, err = this.tx.Prepare(sql + " FOR UPDATE") + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼更新sql +func (this *TxQuery) UpdateStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + if len(this.where) < 1 { + return errors.New("参数错误,缺少条件") + } + + dbName := getTableName(this.dbname, this.table) + + var sql string + + sql = StringJoin("update ", dbName, " set ", strings.Join(this.data, " , ")) + + sql = StringJoin(sql, " where ", strings.Join(this.where, " and ")) + + if this.debug { + log.Println("update sql:", sql, this.value) + } + + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + stmt, err = this.tx.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼插入sql +func (this *TxQuery) CreateStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + + dbName := getTableName(this.dbname, this.table) + + var sql string + + sql = StringJoin("insert into ", dbName, " set ", strings.Join(this.data, " , ")) + + if this.debug { + log.Println("insert sql:", sql, this.value) + } + + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + stmt, err = this.tx.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +// 拼删除sql +func (this *TxQuery) DeleteStmt() error { + + if this.dbname == "" && this.table == "" { + return errors.New("参数错误,没有数据表") + } + if len(this.where) < 1 { + return errors.New("参数错误,缺少条件") + } + + dbName := getTableName(this.dbname, this.table) + + var sql string + + sql = StringJoin("delete from ", dbName, " where ", strings.Join(this.where, " and ")) + + if this.page_size > 0 { + sql = StringJoin(sql, " limit ", strconv.Itoa(this.page_size)) + } + + if this.debug { + log.Println("delete sql:", sql, this.value) + } + + condition_len := 0 //所有条件数 + + for _, ch2 := range sql { + if string(ch2) == "?" { + condition_len++ + } + } + if condition_len != len(this.value) { + return errors.New("参数错误,条件值错误") + } + + stmt, err = this.tx.Prepare(sql) + + if err != nil { + return err + } + + this.stmt = stmt + + return nil +} + +/** + * 执行查询列表 + * return list error + */ +func (this *TxQuery) Select() ([]map[string]string, error) { + + err := this.QueryStmt() + if err != nil { + return []map[string]string{}, err + } + + if this.stmt == nil { + return []map[string]string{}, errors.New("缺少必要参数") + } + + return StmtForQueryList(this.stmt, this.value) +} + +/** + * 执行查询一条数据 + * return row error + */ +func (this *TxQuery) Find() (map[string]string, error) { + this.page = 1 + this.page_size = 1 + err := this.QueryStmt() + if err != nil { + return map[string]string{}, err + } + + if this.stmt == nil { + return nil, errors.New("缺少必要参数") + } + return StmtForQueryRow(this.stmt, this.value) +} + +/** + * 执行更新 + * return is_updated error + */ +func (this *TxQuery) Update() (int64, error) { + + err := this.UpdateStmt() + if err != nil { + return 0, err + } + + return StmtForUpdateExec(this.stmt, this.value) +} + +/** + * 执行删除 + * return is_delete error + */ +func (this *TxQuery) Delete() (int64, error) { + + err := this.DeleteStmt() + if err != nil { + return 0, err + } + + return StmtForUpdateExec(this.stmt, this.value) +} + +/** + * 执行写入 + * return is_insert error + */ +func (this *TxQuery) Create() (int64, error) { + + err := this.CreateStmt() + if err != nil { + return 0, err + } + + return StmtForInsertExec(this.stmt, this.value) +} + +/** + * 提交 + */ +func (this *TxQuery) Commit() error { + return this.tx.Commit() +} + +/** + * 回滚 + */ +func (this *TxQuery) Rollback() error { + return this.tx.Rollback() +}