GO语言操作SQLSever

package store

import (
    "context"
    "database/sql"
    . "ffqp_go/src/common"
    "fmt"
    _ "github.com/denisenkom/go-mssqldb"
    "reflect"
    "strconv"
    "time"
)

type sql_task struct {
    sql string
    v   []interface{}
}

var (
    db_in_thread_chan = make(chan sql_task, 1000)
    DBCon             *sql.DB
    SQL_TIME_NULL     = SQL_TIME{Valid: false}
)

func SQL_INIT() error {

    conn_str := fmt.Sprintf("server=%s;user id=%s;password=%s;port=%d;database=%s;log=0;",
        "localhost", "sa", DB_PWD, 1433, "sadb")
    conn, err := sql.Open("sqlserver", conn_str)
    if err != nil {
        TRACE_ERROR(err)
        return err
    }
    if err := conn.Ping(); err != nil {
        TRACE_ERROR(err)
        return err
    }
    conn.SetMaxOpenConns(48)
    conn.SetMaxIdleConns(24)
    DBCon = conn
    return nil
}

type SQL_TIME struct {
    Time  time.Time
    Valid bool
}

func (c SQL_TIME) IsNotToday() bool {
    return !c.IsToday()
}

func (c SQL_TIME) IsToday() bool {
    if !c.Valid {
        return false
    }
    return IS_TOADY(c.Time)
}

func (c SQL_TIME) String() string {
    return TIME_2_STR(c.Time)
}

type SQL_VALUE struct {
    db_name string
    db_val  interface{}
}

func (c SQL_VALUE) Int() int64 {
    if c.db_val == nil {
        return 0
    }
    rv := reflect.ValueOf(c.db_val)
    switch rv.Kind() {
    case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Int,
        reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
        return rv.Int()
    default:
        TRACE_ERROR(LOGIC("SQL_VALUE TYPE LOGIC Int:" + c.db_name))
    }
    return 0
}

func (c SQL_VALUE) String() string {
    rv := reflect.ValueOf(c.db_val)
    switch rv.Kind() {
    case reflect.String:
        return c.db_val.(string)
    case reflect.Slice:
        switch (c.db_val).(type) {
        case []uint8:
            return string((c.db_val).([]uint8))
        }
    case reflect.Uint, reflect.Uint8, reflect.Uint16,
        reflect.Uint32, reflect.Uint64, reflect.Int,
        reflect.Int8, reflect.Int16, reflect.Int32,
        reflect.Int64:
        return ITOA64(rv.Int())
    case reflect.Float64, reflect.Float32:
        return strconv.FormatFloat(rv.Float(), 'f', 6, 64)
    }
    return "UNKNWONTYPE:" + c.db_name
}

func (c SQL_VALUE) Str() string {
    if c.db_val == nil {
        return ""
    }
    rv := reflect.ValueOf(c.db_val)
    switch rv.Kind() {
    case reflect.String:
        return c.db_val.(string)
    case reflect.Slice:
        switch (c.db_val).(type) {
        case []uint8:
            return string((c.db_val).([]uint8))
        }
    default:
        TRACE_ERROR(LOGIC("SQL_VALUE TYPE LOGIC Str:" + c.db_name))
    }
    return ""
}

func (c SQL_VALUE) Float() float64 {
    if c.db_val == nil {
        return 0
    }
    rv := reflect.ValueOf(c.db_val)
    switch rv.Kind() {
    case reflect.Float64, reflect.Float32:
        return rv.Float()
    default:
        TRACE_ERROR(LOGIC("SQL_VALUE TYPE LOGIC Float:" + c.db_name))
    }
    return 0
}

func (c SQL_VALUE) Bool() bool {
    return c.Int() != 0
}

func (c SQL_VALUE) Tm() SQL_TIME {
    if c.db_val == nil {
        return SQL_TIME{Valid: false}
    }
    return SQL_TIME{Valid: true, Time: c.db_val.(time.Time)}
}

func (c SQL_VALUE) TmStr() string {
    tm := c.Tm()
    if !tm.Valid {
        return ""
    }
    return TIME_2_STR(tm.Time)
}

func SQL_EXEC(sql_str string, v ...interface{}) error {
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        return err
    }
    ctx := context.Background()
    _, err = stmt.ExecContext(ctx, sql_param(v)...)
    if err != nil {
        return err
    }

    return nil
}

func SQL_EXEC_I(sql_str string, v ...interface{}) {
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        LOG.Printf(err.Error() + "\n SQL IS:" + fmt.Sprintf(sql_str, v...))
        return
    }
    ctx := context.Background()
    _, err = stmt.ExecContext(ctx, v...)
    if err != nil {
        LOG.Printf(err.Error() + "\n SQL IS:" + fmt.Sprintf(sql_str, v...))
        return
    }
}

func SQL_INSERT(sql_str string, v ...interface{}) (int64, error) {
    inert_id := int64(0)
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        return inert_id, err
    }
    ctx := context.Background()
    rs, err := stmt.ExecContext(ctx, sql_param(v)...)
    if err != nil {
        return inert_id, err
    }
    rows_affect, err := rs.RowsAffected()
    if err != nil {
        return inert_id, err
    }
    if rows_affect != 0 {
        inert_id, err = rs.LastInsertId()
        if err != nil {
            inert_id = 0
        }
    }
    return inert_id, err
}
func SQL_ARRAY_I(sql_str string, v ...interface{}) ([]map[string]SQL_VALUE, error) {
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        return nil, err
    }
    defer stmt.Close()
    ctx := context.Background()
    rows, err := stmt.QueryContext(ctx, sql_param(v)...)
    if err != nil {
        return nil, err
    }
    defer rows.Close()

    columns, err := rows.Columns()
    var result_dict = make([]map[string]SQL_VALUE, 0)
    for rows.Next() {
        values := make([]interface{}, len(columns))
        scan_args := make([]interface{}, len(columns))
        values_map := make(map[string]SQL_VALUE)
        for i := range values {
            scan_args[i] = &values[i]
        }
        err = rows.Scan(scan_args...)
        for i := range columns {
            values_map[columns[i]] = SQL_VALUE{columns[i], values[i]}
        }
        result_dict = append(result_dict, values_map)
        if err != nil {
            return nil, err
        }
    }
    return result_dict, nil
}

func SQL_ARRAY(sql_str string, v ...interface{}) ([]map[string]SQL_VALUE, error) {

    return SQL_ARRAY_I(sql_str, v...)
}

func SQL_IS_EXIST(sql_str string, v ...interface{}) (bool, error) {
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        return false, err
    }
    defer stmt.Close()
    ctx := context.Background()
    rows, err := stmt.QueryContext(ctx, sql_param(v)...)
    if err != nil {
        return false, err
    }
    defer rows.Close()
    for rows.Next() {
        return true, nil
    }
    return false, nil
}

func SQL_IS_NOT_EXIST(sql_str string, v ...interface{}) (bool, error) {
    ret, err := SQL_IS_EXIST(sql_str, v...)
    if err != nil {
        ret = !ret
    }
    return ret, err
}

func SQL_ROW(sql_str string, v ...interface{}) (map[string]SQL_VALUE, error) {
    stmt, err := DBCon.Prepare(sql_str)
    if err != nil {
        return nil, err
    }
    defer stmt.Close()
    ctx := context.Background()
    rows, err := stmt.QueryContext(ctx, sql_param(v)...)
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    columns, err := rows.Columns()
    for rows.Next() {
        values := make([]interface{}, len(columns))
        scan_args := make([]interface{}, len(columns))
        values_map := make(map[string]SQL_VALUE)
        for i := range values {
            scan_args[i] = &values[i]
        }
        err = rows.Scan(scan_args...)
        if err != nil {
            return nil, err
        }
        for i := range values {
            values_map[columns[i]] = SQL_VALUE{columns[i], values[i]}
        }
        return values_map, nil
    }
    return nil, nil
}

func sql_param(v []interface{}) []interface{} {
    var ps []interface{}
    for _, p := range v {
        sql_v, ok := p.(SQL_VALUE)
        if ok {
            ps = append(ps, sql_v.db_val)
        } else {
            ps = append(ps, p)
        }
    }
    return ps
}

func SQL_IN_THREAD(sql_str string, v ...interface{}) {
    packet := new(sql_task)
    packet.sql = sql_str
    packet.v = v
    db_in_thread_chan <- *packet
}

func DB_IN_THREAD() {
    go func() {
        select {
        case sql_task := <-db_in_thread_chan:
            _ = SQL_EXEC(sql_task.sql, sql_task.v...)
        default:
            time.Sleep(5 * time.Second)
        }
    }()
}

func SQL_PROC(sql_str string, v ...interface{}) ([][]map[string]SQL_VALUE, error) {
    stmt, err := DBCon.Prepare("DECLARE @RC int;" + sql_str + ";SELECT @RC AS RET;")
    if err != nil {
        return nil, err
    }
    defer stmt.Close()
    ctx := context.Background()
    rows, err := stmt.QueryContext(ctx, sql_param(v)...)
    if err != nil {
        return nil, err
    }
    defer rows.Close()
    var result_sets [][]map[string]SQL_VALUE
    for {
        columns, err := rows.Columns()
        var result_dict = make([]map[string]SQL_VALUE, 0)
        for rows.Next() {
            values := make([]interface{}, len(columns))
            scan_args := make([]interface{}, len(columns))
            values_map := make(map[string]SQL_VALUE)
            for i := range values {
                scan_args[i] = &values[i]
            }
            err = rows.Scan(scan_args...)
            for i := range columns {
                values_map[columns[i]] = SQL_VALUE{columns[i], values[i]}
            }
            result_dict = append(result_dict, values_map)
            if err != nil {
                return nil, err
            }
        }
        result_sets = append(result_sets, result_dict)
        if !rows.NextResultSet() {
            break
        }
    }

    return result_sets, nil
}

 

发表评论

邮箱地址不会被公开。 必填项已用*标注