1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-28 01:52:00 +08:00
2017-12-01 04:59:21 +08:00

179 lines
4.5 KiB
Go

package mdb // {{{
// }}}
import ( // {{{
"context"
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt"
)
// }}}
type MDB struct {
*sql.DB
*ctx.Context
}
func (mdb *MDB) Spawn(c *ctx.Context, m *ctx.Message, arg ...string) ctx.Server { // {{{
c.Caches = map[string]*ctx.Cache{
"source": &ctx.Cache{Name: "数据库参数", Value: "", Help: "数据库参数"},
"driver": &ctx.Cache{Name: "数据库驱动", Value: "", Help: "数据库驱动"},
}
c.Configs = map[string]*ctx.Config{}
if len(arg) > 0 {
m.Cap("source", arg[0])
}
if len(arg) > 1 {
m.Cap("driver", arg[1])
} else {
m.Cap("driver", m.Conf("driver"))
}
s := new(MDB)
s.Context = c
return s
}
// }}}
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { // {{{
return mdb
}
// }}}
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { // {{{
if len(arg) > 0 {
m.Cap("source", arg[0])
}
if len(arg) > 1 {
m.Cap("driver", arg[1])
} else {
m.Cap("driver", m.Conf("driver"))
}
if m.Cap("source") == "" || m.Cap("driver") == "" {
return false
}
db, e := sql.Open(m.Cap("driver"), m.Cap("source"))
m.Assert(e)
mdb.DB = db
m.Log("info", "%s: %d open %s %s", mdb.Name, m.Capi("nsource", 1), m.Cap("driver"), m.Cap("source"))
return false
}
// }}}
func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { // {{{
if mdb.DB != nil && m.Target == mdb.Context {
m.Log("info", "%s: %d close %s %s", mdb.Name, m.Capi("nsource", -1)+1, m.Cap("driver"), m.Cap("source"))
mdb.DB.Close()
mdb.DB = nil
return true
}
return false
}
// }}}
var Index = &ctx.Context{Name: "mdb", Help: "内存数据库",
Caches: map[string]*ctx.Cache{
"nsource": &ctx.Cache{Name: "数据源数量", Value: "0", Help: "已打开数据库的数量"},
},
Configs: map[string]*ctx.Config{
"driver": &ctx.Config{Name: "数据库驱动(mysql)", Value: "mysql", Help: "数据库驱动"},
},
Commands: map[string]*ctx.Command{
"open": &ctx.Command{Name: "open name help [source [driver]]", Help: "打开数据库", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
m.Target = m.Master // {{{
m.Start(arg[0], arg[1], arg[2:]...)
return ""
// }}}
}},
"exec": &ctx.Command{Name: "exec sql [arg]", Help: "执行操作语句",
Appends: map[string]string{"LastInsertId": "最后插入元组的标识", "RowsAffected": "修改元组的数量"},
Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
mdb, ok := m.Target.Server.(*MDB) // {{{
m.Assert(ok, "目标模块类型错误")
m.Assert(len(arg) > 0, "缺少参数")
m.Assert(mdb.DB != nil, "数据库未打开")
which := make([]interface{}, 0, len(arg))
for _, v := range arg[1:] {
which = append(which, v)
}
ret, e := mdb.Exec(arg[0], which...)
m.Assert(e)
id, e := ret.LastInsertId()
m.Assert(e)
n, e := ret.RowsAffected()
m.Assert(e)
m.Add("append", "LastInsertId", fmt.Sprintf("%d", id))
m.Add("append", "RowsAffected", fmt.Sprintf("%d", n))
m.Log("info", "%s: last(%d) rows(%d)", m.Target.Name, id, n)
return ""
// }}}
}},
"query": &ctx.Command{Name: "query sql [arg]", Help: "执行查询语句", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
mdb, ok := m.Target.Server.(*MDB) // {{{
m.Assert(ok, "目标模块类型错误")
m.Assert(len(arg) > 0, "缺少参数")
m.Assert(mdb.DB != nil, "数据库未打开")
which := make([]interface{}, 0, len(arg))
for _, v := range arg[1:] {
which = append(which, v)
}
rows, e := mdb.Query(arg[0], which...)
m.Assert(e)
defer rows.Close()
cols, e := rows.Columns()
m.Assert(e)
num := len(cols)
for rows.Next() {
vals := make([]interface{}, num)
ptrs := make([]interface{}, num)
for i := range vals {
ptrs[i] = &vals[i]
}
rows.Scan(ptrs...)
for i, k := range cols {
switch b := vals[i].(type) {
case []byte:
m.Add("append", k, string(b))
case int64:
m.Add("append", k, fmt.Sprintf("%d", b))
default:
m.Add("append", k, "")
}
}
}
m.Log("info", "%s: cols(%d) rows(%d)", m.Target.Name, len(m.Meta["append"]), len(m.Meta[m.Meta["append"][0]]))
return ""
// }}}
}},
"close": &ctx.Command{Name: "close name", Help: "关闭数据库", Hand: func(c *ctx.Context, m *ctx.Message, key string, arg ...string) string {
msg := m.Find(arg[0], m.Master) // {{{
msg.Target.Close(msg)
return ""
// }}}
}},
},
}
func init() {
mdb := &MDB{}
mdb.Context = Index
ctx.Index.Register(Index, mdb)
}