123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441 |
- package db
- import (
- "database/sql"
- "errors"
- "fmt"
- "strconv"
- "time"
- "zhiyuan/pkg/config"
- "zhiyuan/pkg/logger"
- "zhiyuan/pkg/utils"
- "github.com/didi/gendry/builder"
- "github.com/didi/gendry/scanner"
- _ "github.com/go-sql-driver/mysql"
- )
- var db *sql.DB
- var GeoDB *sql.DB
- func Setup() {
- var err error
- db, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=True&loc=Local",
- config.Cfg.Database.User,
- config.Cfg.Database.Password,
- config.Cfg.Database.Host,
- config.Cfg.Database.Name,
- config.Cfg.Database.Charset))
- if err != nil {
- logger.Sugar.Error(err)
- }
- GeoDB, err = sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=%s&parseTime=True&loc=Local",
- config.Cfg.Database.User,
- config.Cfg.Database.Password,
- config.Cfg.Database.Host,
- "geo",
- config.Cfg.Database.Charset))
- if err != nil {
- logger.Sugar.Error(err)
- }
- scanner.SetTagName("json")
- return
- }
- func Query(query string, params map[string]interface{}, retVal interface{}, dbs *sql.DB) error {
- if dbs == nil {
- dbs = db
- }
- cond, values, err := builder.NamedQuery(query, params)
- if err != nil {
- return err
- }
- logger.Sugar.Infof("query: %v; params: %v", cond, values)
- rows, err := dbs.Query(cond, values...)
- // defer rows.Close()
- if err != nil {
- logger.Sugar.Error(err)
- return err
- }
- return scanner.ScanClose(rows, retVal)
- }
- func resolveDataFromRows(rows *sql.Rows) ([]map[string]interface{}, error) {
- if nil == rows {
- return nil, errors.New("[scanner]: rows can't be nil")
- }
- columns, err := rows.Columns()
- if nil != err {
- return nil, err
- }
- length := len(columns)
- var result []map[string]interface{}
- //unnecessary to put below into rows.Next loop,reduce allocating
- values := make([]interface{}, length)
- for i := 0; i < length; i++ {
- values[i] = new(interface{})
- }
- for rows.Next() {
- err = rows.Scan(values...)
- if nil != err {
- return nil, err
- }
- mp := make(map[string]interface{})
- for idx, name := range columns {
- //mp[name] = reflect.ValueOf(values[idx]).Elem().Interface()
- mp[name] = *(values[idx].(*interface{}))
- }
- result = append(result, mp)
- }
- return result, nil
- }
- type CloseErr struct {
- err error
- }
- func (e CloseErr) Error() string {
- return e.err.Error()
- }
- func newCloseErr(err error) error {
- if err == nil {
- return nil
- }
- return CloseErr{err}
- }
- func QueryMap(query string, params map[string]interface{}, dbs *sql.DB) ([]map[string]interface{}, error) {
- if dbs == nil {
- dbs = db
- }
- cond, values, err := builder.NamedQuery(query, params)
- if err != nil {
- return nil, err
- }
- //logger.Sugar.Infof("query: %v; params: %v", cond, values)
- rows, err := dbs.Query(cond, values...)
- // defer rows.Close()
- if err != nil {
- logger.Sugar.Error(err)
- return nil, err
- }
- //result, err := scanner.ScanMapDecodeClose(rows)
- results, err := resolveDataFromRows(rows)
- if nil != err {
- return nil, err
- }
- for i := 0; i < len(results); i++ {
- for k, v := range results[i] {
- rv, ok := v.([]uint8)
- if !ok {
- continue
- }
- s := string(rv)
- results[i][k] = s
- if len(s) > 8 {
- continue
- }
- //convert to int
- intVal, err := strconv.Atoi(s)
- if err == nil {
- results[i][k] = intVal
- continue
- }
- //convert to float64
- floatVal, err := strconv.ParseFloat(s, 64)
- if err == nil {
- results[i][k] = floatVal
- continue
- }
- }
- }
- if nil != rows {
- errClose := rows.Close()
- if err == nil {
- err = newCloseErr(errClose)
- }
- }
- return results, err
- }
- func BuildInsert(table string, data []map[string]interface{}, dbs *sql.DB) (int64, error) {
- if dbs == nil {
- dbs = db
- }
- cond, values, err := builder.BuildInsert(table, data)
- if nil != err {
- logger.Sugar.Error(err)
- return 0, err
- }
- //logger.Sugar.Infof("query: %v; params: %v", cond, values)
- result, err := dbs.Exec(cond, values...)
- if nil != err || nil == result {
- logger.Sugar.Error(err)
- return 0, err
- }
- return result.LastInsertId()
- }
- func BuildUpdate(table string, where, data map[string]interface{}, dbs *sql.DB) (int64, error) {
- if dbs == nil {
- dbs = db
- }
- cond, values, err := builder.BuildUpdate(table, where, data)
- if nil != err {
- return 0, err
- }
- //logger.Sugar.Infof("query: %v; params: %v", cond, values)
- result, err := dbs.Exec(cond, values...)
- if nil != err || nil == result {
- logger.Sugar.Error(err)
- return 0, err
- }
- return result.RowsAffected()
- }
- func GetMultiMap(table string, where map[string]interface{}, fields []string) ([]map[string]interface{}, error) {
- rows, err := BuildSelectRows(table, where, fields)
- if err != nil {
- return nil, err
- }
- result, mapErr := scanner.ScanMapDecodeClose(rows)
- return result, mapErr
- }
- func GetMulti(table string, where map[string]interface{}, fields []string, retVal interface{}) error {
- rows, err := BuildSelectRows(table, where, fields)
- if err != nil {
- return err
- }
- return ScanClose(rows, retVal)
- }
- func GetOneMap(table string, where map[string]interface{}, fields []string) (map[string]interface{}, error) {
- wheres := make(map[string]interface{})
- for key, value := range where {
- wheres[key] = value
- }
- wheres["_limit"] = []uint{1}
- result, err := GetMultiMap(table, wheres, fields)
- if err != nil {
- return nil, err
- }
- if len(result) == 0 {
- return nil, nil
- }
- return result[0], nil
- }
- func GetOne(table string, where map[string]interface{}, fields []string, retVal interface{}) error {
- wheres := make(map[string]interface{})
- for key, value := range where {
- wheres[key] = value
- }
- wheres["_limit"] = []uint{1}
- return GetMulti(table, where, fields, retVal)
- }
- func ScanClose(rows *sql.Rows, target interface{}) error {
- err := scanner.ScanClose(rows, target)
- if err == scanner.ErrEmptyResult {
- return nil
- }
- return err
- }
- func Count(table string, where map[string]interface{}) (int64, error) {
- res, err := GetOneMap(table, where, []string{"count(*) as count"})
- if err != nil {
- return 0, err
- }
- return res["count"].(int64), err
- }
- func BuildSelectRows(table string, where map[string]interface{}, fields []string) (*sql.Rows, error) {
- cond, values, err := BuildSelect(table, where, fields)
- if err != nil {
- return nil, err
- }
- return GetRows(cond, values)
- }
- func BuildSelect(table string, where map[string]interface{}, fields []string) (string, []interface{}, error) {
- cond, values, err := builder.BuildSelect(table, where, fields)
- if err != nil {
- logger.Sugar.Error(err)
- }
- return cond, values, err
- }
- func GetRows(cond string, values []interface{}) (*sql.Rows, error) {
- logger.Sugar.Infof("query: %v; params: %v", cond, values)
- rows, err := db.Query(cond, values...)
- // defer rows.Close()
- if err != nil {
- logger.Sugar.Error(err)
- return nil, errors.New("未知错误")
- }
- return rows, nil
- }
- func CountRaw(query string, params map[string]interface{}) (int64, error) {
- res, err := GetOneMapRaw("SELECT count(*) as count FROM "+query, params)
- if err != nil {
- return 0, err
- }
- return utils.ToInt64(res["count"]), err
- }
- func GetMultiRaw(query string, where map[string]string, params map[string]interface{}, retVal interface{}) error {
- cond, values, err := builder.NamedQuery(JoinQuery(query, where), params)
- if err != nil {
- return err
- }
- rows, err := GetRows(cond, values)
- if err != nil {
- return err
- }
- return scanner.ScanClose(rows, retVal)
- }
- func JoinQuery(query string, where map[string]string) string {
- if where["where"] != "" {
- query = query + " WHERE " + where["where"]
- }
- if where["_group_by"] != "" {
- query = query + " GROUP BY " + where["_group_by"]
- }
- if where["_having"] != "" {
- query = query + " HAVING " + where["_having"]
- }
- if where["_order_by"] != "" {
- query = query + " ORDER BY " + where["_order_by"]
- }
- if where["_page_size"] != "" && where["_page_num"] != "" {
- pageNum := utils.ToInt(where["_page_num"])
- pageSize := utils.ToInt(where["_page_size"])
- query = query + " LIMIT " + utils.ToStr((pageNum-1)*pageSize) + "," + utils.ToStr(pageSize)
- }
- return query
- }
- func GetMultiMapRaw(query string, params map[string]interface{}) ([]map[string]interface{}, error) {
- cond, values, err := builder.NamedQuery(query, params)
- if err != nil {
- return nil, err
- }
- rows, err := GetRows(cond, values)
- if err != nil {
- return nil, err
- }
- result, mapErr := scanner.ScanMapDecodeClose(rows)
- return result, mapErr
- }
- func GetOneMapRaw(query string, params map[string]interface{}) (map[string]interface{}, error) {
- result, err := GetMultiMapRaw(query, params)
- if err != nil {
- return nil, err
- }
- if len(result) == 0 {
- return nil, errors.New("empty record1")
- }
- return result[0], err
- }
- func UpdateRaw(query string, params map[string]interface{}) (int64, error) {
- cond, values, err := builder.NamedQuery(query, params)
- if err != nil {
- return 0, err
- }
- return GetUpdateResult(cond, values)
- }
- func UpdateRawSimple(table string, querySet, queryWhere string, params map[string]interface{}) (int64, error) {
- querySet = querySet + ",updated_at=" + utils.ToStr(time.Now().Unix())
- query := fmt.Sprintf("UPDATE %s SET %s WHERE %s", table, querySet, queryWhere)
- return UpdateRaw(query, params)
- }
- func InsertRaw(query string, params map[string]interface{}) (int64, error) {
- cond, values, err := builder.NamedQuery(query, params)
- if err != nil {
- return 0, err
- }
- return GetInsertResult(cond, values)
- }
- func Update(table string, where, data map[string]interface{}) (int64, error) {
- data["updated_at"] = time.Now().Unix()
- cond, values, err := builder.BuildUpdate(table, where, data)
- if nil != err {
- return 0, err
- }
- return GetUpdateResult(cond, values)
- }
- func Delete(table string, where map[string]interface{}) (int64, error) {
- cond, values, err := builder.BuildDelete(table, where)
- if nil != err {
- return 0, err
- }
- return GetUpdateResult(cond, values)
- }
- func DeleteSoft(table string, where map[string]interface{}) (int64, error) {
- cond, values, err := builder.BuildUpdate(table, where, map[string]interface{}{"deleted_at": time.Now().Unix()})
- if nil != err {
- return 0, err
- }
- return GetUpdateResult(cond, values)
- }
- func Insert(table string, data []map[string]interface{}) (int64, error) {
- for k, v := range data {
- v["created_at"] = time.Now().Unix()
- v["updated_at"] = time.Now().Unix()
- data[k] = v
- }
- cond, values, err := builder.BuildInsert(table, data)
- if nil != err {
- logger.Sugar.Error(err)
- return 0, err
- }
- return GetInsertResult(cond, values)
- }
- func InsertOne(table string, data map[string]interface{}) (int64, error) {
- return Insert(table, []map[string]interface{}{data})
- }
- func GetUpdateResult(cond string, values []interface{}) (int64, error) {
- result, err := Exec(cond, values)
- if err != nil {
- return 0, err
- }
- return result.RowsAffected()
- }
- func GetInsertResult(cond string, values []interface{}) (int64, error) {
- result, err := Exec(cond, values)
- if err != nil {
- return 0, err
- }
- return result.LastInsertId()
- }
- func Exec(cond string, values []interface{}) (sql.Result, error) {
- //logger.Sugar.Infof("query: %v; params: %v", cond, values)
- result, err := db.Exec(cond, values...)
- if nil != err || nil == result {
- logger.Sugar.Error(err)
- return nil, errors.New("未知错误")
- }
- return result, err
- }
- func GetOffset(pageNum uint, pageSize uint) []uint {
- return []uint{(pageNum - 1) * pageSize, pageSize}
- }
|