package db

import (
	"code.hoteas.com/golang/hotime/cache"
	. "code.hoteas.com/golang/hotime/common"
	"database/sql"
	"encoding/json"
	"errors"
	_ "github.com/go-sql-driver/mysql"
	_ "github.com/mattn/go-sqlite3"
	"os"
	"reflect"
	"sort"
	"strings"
)

type HoTimeDB struct {
	*sql.DB
	ContextBase
	DBName string
	*cache.HoTimeCache
	Type        string
	Prefix      string
	LastQuery   string
	LastData    []interface{}
	ConnectFunc func(err ...*Error) (*sql.DB, *sql.DB)
	LastErr     *Error
	limit       Slice
	*sql.Tx     //事务对象
	SlaveDB     *sql.DB
}

// SetConnect 设置数据库配置连接
func (that *HoTimeDB) SetConnect(connect func(err ...*Error) (master, slave *sql.DB), err ...*Error) {
	that.ConnectFunc = connect
	_ = that.InitDb(err...)

}

// GetType 设置数据库配置连接
func (that *HoTimeDB) GetType() string {
	return that.Type
}

// Action 事务，如果action返回true则执行成功；false则回滚
func (that *HoTimeDB) Action(action func(db HoTimeDB) (isSuccess bool)) (isSuccess bool) {
	db := HoTimeDB{DB: that.DB, HoTimeCache: that.HoTimeCache, Prefix: that.Prefix}
	tx, err := db.Begin()
	if err != nil {
		that.LastErr.SetError(err)
		return isSuccess
	}

	db.Tx = tx

	isSuccess = action(db)

	if !isSuccess {
		err = db.Tx.Rollback()
		if err != nil {
			that.LastErr.SetError(err)
			return isSuccess
		}
		return isSuccess
	}
	err = db.Tx.Commit()
	if err != nil {
		that.LastErr.SetError(err)
		return false
	}
	return true
}

func (that *HoTimeDB) InitDb(err ...*Error) *Error {
	if len(err) != 0 {
		that.LastErr = err[0]
	}
	that.DB, that.SlaveDB = that.ConnectFunc(that.LastErr)
	if that.DB == nil {
		return that.LastErr
	}
	e := that.DB.Ping()

	that.LastErr.SetError(e)

	if that.SlaveDB != nil {
		e := that.SlaveDB.Ping()
		that.LastErr.SetError(e)
	}

	return that.LastErr
}

func (that *HoTimeDB) Page(page, pageRow int) *HoTimeDB {
	page = (page - 1) * pageRow
	if page < 0 {
		page = 1
	}

	that.limit = Slice{page, pageRow}
	return that
}

func (that *HoTimeDB) PageSelect(table string, qu ...interface{}) []Map {

	if len(qu) == 1 {
		qu = append(qu, Map{"LIMIT": that.limit})
	}
	if len(qu) == 2 {
		temp := DeepCopyMap(qu[1]).(Map)
		temp["LIMIT"] = that.limit
		qu[1] = temp
	}
	if len(qu) == 3 {
		temp := DeepCopyMap(qu[2]).(Map)
		temp["LIMIT"] = that.limit
		qu[2] = temp
	}
	//fmt.Println(qu)
	data := that.Select(table, qu...)

	return data
}

// Row 数据库数据解析
func (that *HoTimeDB) Row(resl *sql.Rows) []Map {
	dest := make([]Map, 0)
	strs, _ := resl.Columns()

	for i := 0; resl.Next(); i++ {
		lis := make(Map, 0)
		a := make([]interface{}, len(strs))

		b := make([]interface{}, len(a))
		for j := 0; j < len(a); j++ {
			b[j] = &a[j]
		}
		err := resl.Scan(b...)
		if err != nil {
			that.LastErr.SetError(err)
			return nil
		}
		for j := 0; j < len(a); j++ {
			//fmt.Println(reflect.ValueOf(a[j]).Type().String() )
			if a[j] != nil && reflect.ValueOf(a[j]).Type().String() == "[]uint8" {
				lis[strs[j]] = string(a[j].([]byte))
			} else {
				lis[strs[j]] = a[j] //取实际类型
			}

		}
		//防止int被误读为float64
		//jlis, e := json.Marshal(lis)
		//if e != nil {
		//	that.LastErr.SetError(e)
		//} else {
		//	lis.JsonToMap(string(jlis), that.LastErr)
		//}

		dest = append(dest, lis)

	}

	return dest
}

//
////code=0,1,2 0 backup all,1 backup data,2 backup ddl
//func (that *HoTimeDB) Backup(path string, code int) {
//	var cmd *exec.Cmd
//	switch code {
//	case 0:cmd= exec.Command("mysqldump","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]),ObjToStr(Config["dbName"]))
//	case 1:cmd= exec.Command("mysqldump","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]), ObjToStr(Config["dbName"]))
//	case 2:cmd= exec.Command("mysqldump","--no-data","-h"+ObjToStr(Config["dbHost"]), "-P"+ObjToStr(Config["dbPort"]),"-u"+ObjToStr(Config["dbUser"]), "-p"+ObjToStr(Config["dbPwd"]),ObjToStr(Config["dbName"]))
//	}
//
//
//
//	stdout, err := cmd.StdoutPipe()
//	if err != nil {
//		log.Println(err)
//	}
//
//	if err := cmd.Start(); err != nil {
//		log.Println(err)
//	}
//
//	bytes, err := ioutil.ReadAll(stdout)
//	if err != nil {
//		log.Println(err)
//	}
//	err = ioutil.WriteFile(path, bytes, 0644)
//	if err != nil {
//		panic(err)
//	}
//	return ;
//	//
//	//db := ``
//	//fmt.Println(db)
//	//
//	//tables := that.Query("show tables")
//	//lth := len(tables)
//	//if lth == 0 {
//	//	return
//	//}
//	//for k, _ := range tables[0] {
//	//	db = Substr(k, 10, len(k))
//	//}
//	//
//	//fd, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
//	//fd.Write([]byte("/*datetime " + time.Now().Format("2006-01-02 15:04:05") + "  */ \r\n"))
//	//fd.Close()
//	//
//	//for i := 0; i < lth; i++ {
//	//	tt := tables[i]["Tables_in_"+db].(string)
//	//	that.backupSave(path, tt, code)
//	//	debug.FreeOSMemory()
//	//}
//
//}

func (that *HoTimeDB) backupSave(path string, tt string, code int) {
	fd, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
	defer fd.Close()

	str := "\r\n"
	if code == 0 || code == 2 {
		str += that.backupDdl(tt)
	}

	if code == 0 || code == 1 {
		str += "insert  into `" + tt + "`\r\n\r\n("
		str += that.backupCol(tt)
	}

	_, _ = fd.Write([]byte(str))
}
func (that *HoTimeDB) backupDdl(tt string) string {

	data := that.Query("show create table " + tt)
	if len(data) == 0 {
		return ""
	}

	return ObjToStr(data[0]["Create Table"]) + ";\r\n\r\n"
}

func (that *HoTimeDB) backupCol(tt string) string {
	str := ""
	data := that.Select(tt, "*")

	lthData := len(data)

	if lthData == 0 {
		return str
	}
	lthCol := len(data[0])
	col := make([]string, lthCol)
	tempLthData := 0
	for k := range data[0] {

		if tempLthData == lthCol-1 {
			str += "`" + k + "`)"
		} else {
			str += "`" + k + "`,"
		}
		col[tempLthData] = k
		tempLthData++
	}

	str += " values"

	for j := 0; j < lthData; j++ {

		for m := 0; m < lthCol; m++ {

			if m == 0 {
				str += "("
			}

			v := "NULL"
			if data[j][col[m]] != nil {
				v = "'" + strings.Replace(ObjToStr(data[j][col[m]]), "'", `\'`, -1) + "'"
			}

			if m == lthCol-1 {
				str += v + ")"

			} else {
				str += v + ","
			}
		}
		if j == lthData-1 {
			str += ";\r\n\r\n"
		} else {
			str += ",\r\n\r\n"
		}
	}
	return str
}

func (that *HoTimeDB) md5(query string, args ...interface{}) string {
	strByte, _ := json.Marshal(args)
	str := Md5(query + ":" + string(strByte))
	return str
}

func (that *HoTimeDB) Query(query string, args ...interface{}) []Map {

	//fmt.Println(query)
	var err error
	var resl *sql.Rows

	that.LastQuery = query
	that.LastData = args
	//主从数据库切换，只有select语句有从数据库
	db := that.DB
	if that.SlaveDB != nil {
		db = that.SlaveDB
	}

	if db == nil {
		err = errors.New("没有初始化数据库")
		that.LastErr.SetError(err)
		return nil
	}

	if that.Tx != nil {
		resl, err = that.Tx.Query(query, args...)
	} else {
		resl, err = db.Query(query, args...)
	}

	that.LastErr.SetError(err)
	if err != nil {
		if err = db.Ping(); err != nil {
			that.LastErr.SetError(err)
			_ = that.InitDb()
			if that.LastErr.GetError() != nil {
				return nil
			}
			return that.Query(query, args...)
		}
		return nil
	}

	return that.Row(resl)
}

func (that *HoTimeDB) Exec(query string, args ...interface{}) (sql.Result, *Error) {

	that.LastQuery = query
	that.LastData = args
	var e error
	var resl sql.Result

	if that.DB == nil {
		err := errors.New("没有初始化数据库")
		that.LastErr.SetError(err)
		return nil, that.LastErr
	}

	if that.Tx != nil {
		resl, e = that.Tx.Exec(query, args...)
	} else {
		resl, e = that.DB.Exec(query, args...)
	}

	that.LastErr.SetError(e)

	//判断是否连接断开了
	if e != nil {

		if e = that.DB.Ping(); e != nil {
			that.LastErr.SetError(e)
			_ = that.InitDb()
			if that.LastErr.GetError() != nil {
				return resl, that.LastErr
			}
			return that.Exec(query, args...)
		}
	}

	return resl, that.LastErr
}

//func (that *HoTimeDB)copy(data []Map)[]Map{
//	if data==nil{
//		return nil
//	}
//
//	lth:=len(data)
//
//	res:=make([]Map,lth)
//
//
//	for i:=0;i<lth;i++{
//
//		res[i]=DeepCopy(data[i]).(Map)
//	}
//
//	return res
//
//}

func (that *HoTimeDB) Select(table string, qu ...interface{}) []Map {

	query := "SELECT"
	where := Map{}
	qs := make([]interface{}, 0)
	intQs, intWhere := 0, 1
	join := false
	if len(qu) == 3 {
		intQs = 1
		intWhere = 2
		join = true

	}

	if len(qu) > 0 {
		if reflect.ValueOf(qu[intQs]).Type().String() == "string" {
			query += " " + qu[intQs].(string)
		} else {
			for i := 0; i < len(qu[intQs].(Slice)); i++ {
				k := qu[intQs].(Slice)[i].(string)
				if strings.Contains(k, " AS ") {

					query += " " + k + " "

				} else {
					query += " `" + k + "` "
				}

				if i+1 != len(qu[intQs].(Slice)) {
					query = query + ", "
				}

			}
		}

	} else {
		query += " *"
	}
	if !strings.Contains(table, ".") && !strings.Contains(table, " AS ") {
		query += " FROM `" + that.Prefix + table + "`"
	} else {
		query += " FROM " + that.Prefix + table
	}

	if join {
		var testQu = []string{}
		testQuData := qu[0].(Map)
		for key, _ := range testQuData {
			//fmt.Println(key, ":", value)
			testQu = append(testQu, key)
		}
		sort.Strings(testQu)

		for _, k := range testQu {
			v := testQuData[k]
			switch Substr(k, 0, 3) {
			case "[>]":
				query += " LEFT JOIN `" + Substr(k, 3, len(k)-3) + "` ON " + v.(string)
			case "[<]":
				query += " RIGHT JOIN `" + Substr(k, 3, len(k)-3) + "` ON " + v.(string)
			}
			switch Substr(k, 0, 4) {
			case "[<>]":
				query += " FULL JOIN `" + Substr(k, 4, len(k)-4) + "` ON " + v.(string)
			case "[><]":
				query += " INNER JOIN `" + Substr(k, 4, len(k)-4) + "` ON " + v.(string)
			}
		}
	}

	if len(qu) > 1 {
		where = qu[intWhere].(Map)
	}

	temp, resWhere := that.where(where)

	query += temp
	qs = append(qs, resWhere...)
	md5 := that.md5(query, qs...)

	if that.HoTimeCache != nil && table != "cached" {
		//如果缓存有则从缓存取
		cacheData := that.HoTimeCache.Db(table + ":" + md5)

		if cacheData != nil && cacheData.Data != nil {
			return cacheData.ToMapArray()
		}
	}

	//无缓存则数据库取
	res := that.Query(query, qs...)

	if res == nil {
		res = []Map{}
	}

	//缓存
	if that.HoTimeCache != nil && table != "cached" {

		_ = that.HoTimeCache.Db(table+":"+md5, res)
	}

	return res

}

func (that *HoTimeDB) Get(table string, qu ...interface{}) Map {
	//fmt.Println(qu)
	if len(qu) == 1 {
		qu = append(qu, Map{"LIMIT": 1})
	}
	if len(qu) == 2 {
		temp := qu[1].(Map)
		temp["LIMIT"] = 1
		qu[1] = temp
	}
	if len(qu) == 3 {
		temp := qu[2].(Map)
		temp["LIMIT"] = 1
		qu[2] = temp
	}
	//fmt.Println(qu)
	data := that.Select(table, qu...)
	if len(data) == 0 {
		return nil
	}
	return data[0]
}
func (that *HoTimeDB) GetPrefix() string {
	return that.Prefix
}

// Count 计数
func (that *HoTimeDB) Count(table string, qu ...interface{}) int {
	var req = []interface{}{}
	if len(qu) == 2 {
		req = append(req, qu[0])
		req = append(req, "COUNT(*)")
		req = append(req, qu[1])
	} else {
		req = append(req, "COUNT(*)")
		req = append(req, qu...)
	}

	//req=append(req,qu...)
	data := that.Select(table, req...)
	//fmt.Println(data)
	if len(data) == 0 {
		return 0
	}
	//res,_:=StrToInt(data[0]["COUNT(*)"].(string))
	res := ObjToStr(data[0]["COUNT(*)"])
	count, _ := StrToInt(res)
	return count

}

var condition = []string{"AND", "OR"}
var vcond = []string{"GROUP", "ORDER", "LIMIT"}

//where语句解析
func (that *HoTimeDB) where(data Map) (string, []interface{}) {

	where := ""

	res := make([]interface{}, 0)
	//AND OR判断
	testQu := []string{}
	//testQuData:= qu[0].(Map)
	for key, _ := range data {
		//fmt.Println(key, ":", value)
		testQu = append(testQu, key)
	}
	sort.Strings(testQu)
	for _, k := range testQu {
		v := data[k]
		x := 0
		for i := 0; i < len(condition); i++ {

			if condition[i] == k {

				tw, ts := that.cond(k, v.(Map))

				where += tw
				res = append(res, ts...)
				break
			}
			x++
		}

		y := 0
		for j := 0; j < len(vcond); j++ {

			if vcond[j] == k {
				break
			}
			y++
		}
		if x == len(condition) && y == len(vcond) {

			if v != nil && reflect.ValueOf(v).Type().String() == "common.Slice" && len(v.(Slice)) == 0 {
				continue
			}

			if v != nil && reflect.ValueOf(v).Type().String() == "[]interface {}" && len(v.([]interface{})) == 0 {
				continue
			}

			tv, vv := that.varCond(k, v)

			where += tv
			res = append(res, vv...)
		}

	}

	if len(where) != 0 {
		where = " WHERE " + where
	}

	//特殊字符
	for j := 0; j < len(vcond); j++ {
		testQu := []string{}
		//testQuData:= qu[0].(Map)
		for key, _ := range data {
			//fmt.Println(key, ":", value)
			testQu = append(testQu, key)
		}
		sort.Strings(testQu)
		for _, k := range testQu {
			v := data[k]
			if vcond[j] == k {
				if k == "ORDER" {
					where += " " + k + " BY "
					//fmt.Println(reflect.ValueOf(v).Type())

					//break
				} else if k == "GROUP" {

					where += " " + k + " BY "
				} else {

					where += " " + k
				}

				if reflect.ValueOf(v).Type().String() == "common.Slice" {
					for i := 0; i < len(v.(Slice)); i++ {
						where += " " + ObjToStr(v.(Slice)[i])

						if len(v.(Slice)) != i+1 {
							where += ","
						}

					}

				} else {
					//fmt.Println(v)
					where += " " + ObjToStr(v)
				}

				break
			}
		}

	}

	return where, res

}

func (that *HoTimeDB) varCond(k string, v interface{}) (string, []interface{}) {

	where := ""
	res := make([]interface{}, 0)
	length := len(k)
	if k == "[#]" {
		k = strings.Replace(k, "[#]", "", -1)
		where += " " + ObjToStr(v) + " "
	} else if length > 0 && strings.Contains(k, "[") && k[length-1] == ']' {
		def := false

		switch Substr(k, length-3, 3) {
		case "[>]":
			k = strings.Replace(k, "[>]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + ">? "
			res = append(res, v)
		case "[<]":
			k = strings.Replace(k, "[<]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + "<? "
			res = append(res, v)
		case "[!]":
			k = strings.Replace(k, "[!]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where, res = that.notIn(k, v, where, res)
		case "[#]":
			k = strings.Replace(k, "[#]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += " " + k + "=" + ObjToStr(v)
		case "[##]": //直接添加value到sql，需要考虑防注入，value比如："a>b"

			where += " " + ObjToStr(v)
		case "[#!]":
			k = strings.Replace(k, "[#!]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += " " + k + "!=" + ObjToStr(v)
		case "[!#]":
			k = strings.Replace(k, "[!#]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += " " + k + "!=" + ObjToStr(v)
		case "[~]":
			k = strings.Replace(k, "[~]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + " LIKE ? "
			v = "%" + ObjToStr(v) + "%"
			res = append(res, v)
		case "[!~]": //左边任意
			k = strings.Replace(k, "[~]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + " LIKE ? "
			v = "%" + ObjToStr(v)
			res = append(res, v)
		case "[~!]": //右边任意
			k = strings.Replace(k, "[~]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + " LIKE ? "
			v = ObjToStr(v) + "%"
			res = append(res, v)
		case "[~~]": //手动任意
			k = strings.Replace(k, "[~]", "", -1)
			if !strings.Contains(k, ".") {
				k = "`" + k + "`"
			}
			where += k + " LIKE ? "
			//v = ObjToStr(v)
			res = append(res, v)
		default:
			def = true

		}
		if def {
			switch Substr(k, length-4, 4) {
			case "[>=]":
				k = strings.Replace(k, "[>=]", "", -1)
				if !strings.Contains(k, ".") {
					k = "`" + k + "`"
				}
				where += k + ">=? "
				res = append(res, v)
			case "[<=]":
				k = strings.Replace(k, "[<=]", "", -1)
				if !strings.Contains(k, ".") {
					k = "`" + k + "`"
				}
				where += k + "<=? "
				res = append(res, v)
			case "[><]":
				k = strings.Replace(k, "[><]", "", -1)
				if !strings.Contains(k, ".") {
					k = "`" + k + "`"
				}
				where += k + " NOT BETWEEN ? AND ? "
				res = append(res, v.(Slice)[0])
				res = append(res, v.(Slice)[1])
			case "[<>]":
				k = strings.Replace(k, "[<>]", "", -1)
				if !strings.Contains(k, ".") {
					k = "`" + k + "`"
				}
				where += k + " BETWEEN ? AND ? "
				res = append(res, v.(Slice)[0])
				res = append(res, v.(Slice)[1])
			default:
				if !strings.Contains(k, ".") {
					k = "`" + k + "`"
				}
				if reflect.ValueOf(v).Type().String() == "common.Slice" {
					where += k + " IN ("
					res = append(res, v.(Slice)...)
					if len(v.(Slice)) == 0 {
						where += ") "
					} else {
						for i := 0; i < len(v.(Slice)); i++ {
							if i+1 != len(v.(Slice)) {
								where += "?,"
							} else {
								where += "?) "
							}
							//res=append(res,(v.(Slice))[i])
						}
					}

				} else {
					where += k + "=? "
					res = append(res, v)
				}

			}
		}

	} else {
		//fmt.Println(reflect.ValueOf(v).Type().String())
		if !strings.Contains(k, ".") {
			k = "`" + k + "`"
		}
		if v == nil {
			where += k + " IS NULL"
		} else if reflect.ValueOf(v).Type().String() == "common.Slice" {

			//fmt.Println(v)
			where += k + " IN ("
			res = append(res, v.(Slice)...)
			for i := 0; i < len(v.(Slice)); i++ {
				if i+1 != len(v.(Slice)) {
					where += "?,"
				} else {
					where += "?) "
				}
				//res=append(res,(v.(Slice))[i])
			}
		} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {

			where += k + " IN ("
			res = append(res, v.([]interface{})...)
			for i := 0; i < len(v.([]interface{})); i++ {
				if i+1 != len(v.([]interface{})) {
					where += "?,"
				} else {
					where += "?) "
				}
				//res=append(res,(v.(Slice))[i])
			}
		} else {

			where += k + "=? "
			res = append(res, v)

		}
	}

	return where, res
}

//	that.Db.Update("user",hotime.Map{"ustate":"1"},hotime.Map{"AND":hotime.Map{"OR":hotime.Map{"uid":4,"uname":"dasda"}},"ustate":1})
func (that *HoTimeDB) notIn(k string, v interface{}, where string, res []interface{}) (string, []interface{}) {
	//where:=""
	//fmt.Println(reflect.ValueOf(v).Type().String())
	if v == nil {

		where += k + " IS NOT NULL "

	} else if reflect.ValueOf(v).Type().String() == "common.Slice" {
		where += k + " NOT IN ("
		res = append(res, v.(Slice)...)
		for i := 0; i < len(v.(Slice)); i++ {
			if i+1 != len(v.(Slice)) {
				where += "?,"
			} else {
				where += "?) "
			}
			//res=append(res,(v.(Slice))[i])
		}
	} else if reflect.ValueOf(v).Type().String() == "[]interface {}" {
		where += k + " NOT IN ("
		res = append(res, v.([]interface{})...)
		for i := 0; i < len(v.([]interface{})); i++ {
			if i+1 != len(v.([]interface{})) {
				where += "?,"
			} else {
				where += "?) "
			}
			//res=append(res,(v.(Slice))[i])
		}
	} else {

		where += k + " !=? "
		res = append(res, v)

	}

	return where, res
}

func (that *HoTimeDB) cond(tag string, data Map) (string, []interface{}) {
	where := " "
	res := make([]interface{}, 0)
	lens := len(data)
	//fmt.Println(lens)
	testQu := []string{}
	//testQuData:= qu[0].(Map)
	for key, _ := range data {
		//fmt.Println(key, ":", value)
		testQu = append(testQu, key)
	}
	sort.Strings(testQu)
	for _, k := range testQu {
		v := data[k]
		x := 0
		for i := 0; i < len(condition); i++ {

			if condition[i] == k {

				tw, ts := that.cond(k, v.(Map))
				if lens--; lens <= 0 {
					//fmt.Println(lens)
					where += "(" + tw + ") "
				} else {
					where += "(" + tw + ") " + tag + " "
				}

				res = append(res, ts...)
				break
			}
			x++
		}

		if x == len(condition) {

			tv, vv := that.varCond(k, v)

			res = append(res, vv...)
			if lens--; lens <= 0 {
				where += tv + ""
			} else {
				where += tv + " " + tag + " "
			}
		}

	}

	return where, res
}

// Update 更新数据
func (that *HoTimeDB) Update(table string, data Map, where Map) int64 {

	query := "UPDATE `" + that.Prefix + table + "` SET "
	//UPDATE Person SET Address = 'Zhongshan 23', City = 'Nanjing' WHERE LastName = 'Wilson'
	qs := make([]interface{}, 0)
	tp := len(data)

	for k, v := range data {
		vstr := "?"
		if Substr(k, len(k)-3, 3) == "[#]" {
			k = strings.Replace(k, "[#]", "", -1)

			vstr = ObjToStr(v)
		} else {
			qs = append(qs, v)
		}
		query += "`" + k + "`=" + vstr + ""
		if tp--; tp != 0 {
			query += ", "
		}
	}

	temp, resWhere := that.where(where)
	//fmt.Println(resWhere)

	query += temp
	qs = append(qs, resWhere...)

	res, err := that.Exec(query, qs...)

	rows := int64(0)
	if err.GetError() == nil && res != nil {
		rows, _ = res.RowsAffected()
	}

	//如果更新成功，则删除缓存
	if rows != 0 {
		if that.HoTimeCache != nil && table != "cached" {
			_ = that.HoTimeCache.Db(table+"*", nil)
		}
	}

	return rows
}

func (that *HoTimeDB) Delete(table string, data map[string]interface{}) int64 {

	query := "DELETE FROM " + that.Prefix + table + " "

	temp, resWhere := that.where(data)
	query += temp

	res, err := that.Exec(query, resWhere...)
	rows := int64(0)
	if err.GetError() == nil && res != nil {
		rows, _ = res.RowsAffected()
	}

	//如果删除成功,删除对应缓存
	if rows != 0 {
		if that.HoTimeCache != nil && table != "cached" {
			_ = that.HoTimeCache.Db(table+"*", nil)
		}
	}
	//return 0

	return rows
}

// Insert 插入新数据
func (that *HoTimeDB) Insert(table string, data map[string]interface{}) int64 {

	values := make([]interface{}, 0)
	queryString := " ("
	valueString := " ("

	lens := len(data)
	tempLen := 0
	for k, v := range data {
		tempLen++

		vstr := "?"
		if Substr(k, len(k)-3, 3) == "[#]" {
			k = strings.Replace(k, "[#]", "", -1)

			vstr = ObjToStr(v)
			if tempLen < lens {
				queryString += "`" + k + "`,"
				valueString += vstr + ","
			} else {
				queryString += "`" + k + "`) "
				valueString += vstr + ");"
			}
		} else {

			values = append(values, v)
			if tempLen < lens {
				queryString += "`" + k + "`,"
				valueString += "?,"
			} else {
				queryString += "`" + k + "`) "
				valueString += "?);"
			}
		}

	}
	query := "INSERT INTO `" + that.Prefix + table + "` " + queryString + "VALUES" + valueString

	res, err := that.Exec(query, values...)

	id := int64(0)
	if err.GetError() == nil && res != nil {
		id1, err := res.LastInsertId()
		that.LastErr.SetError(err)
		id = id1
	}

	//如果插入成功，删除缓存
	if id != 0 {
		if that.HoTimeCache != nil && table != "cached" {
			_ = that.HoTimeCache.Db(table+"*", nil)
		}
	}

	//fmt.Println(id)
	return id
}
