mirror of
https://shylinux.com/x/ContextOS
synced 2025-04-28 01:52:00 +08:00
179 lines
4.5 KiB
Go
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)
|
|
}
|