1
0
mirror of https://shylinux.com/x/ContextOS synced 2025-04-26 01:04:06 +08:00
This commit is contained in:
shaoying 2019-07-27 12:45:01 +08:00
parent c0c9f26fe2
commit 013b38fb1b
2 changed files with 290 additions and 369 deletions

View File

@ -4,5 +4,5 @@ var version = struct {
host string host string
self int self int
}{ }{
"2019-07-27 06:00:22", "mac", 219, "2019-07-27 12:43:56", "ZYB-20190522USI", 276,
} }

View File

@ -1,33 +1,34 @@
package mdb package mdb
import ( import (
"contexts/ctx"
"time"
"toolkit"
"database/sql"
_ "github.com/go-sql-driver/mysql" _ "github.com/go-sql-driver/mysql"
"github.com/gomodule/redigo/redis" "github.com/gomodule/redigo/redis"
"contexts/ctx"
"toolkit"
"database/sql"
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings" "strings"
"time"
) )
type MDB struct { type MDB struct {
*sql.DB
conn redis.Conn conn redis.Conn
*sql.DB
*ctx.Context *ctx.Context
} }
func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server { func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server {
c.Caches = map[string]*ctx.Cache{ c.Caches = map[string]*ctx.Cache{
"database": &ctx.Cache{Name: "database", Value: m.Confx("database", arg, 0), Help: "数据库"}, "database": &ctx.Cache{Name: "database", Value: m.Confx("database", arg, 0), Help: "数据库"},
"username": &ctx.Cache{Name: "username", Value: m.Confx("username", arg, 1), Help: "账户"}, "username": &ctx.Cache{Name: "username", Value: m.Confx("username", arg, 1), Help: "用户名"},
"password": &ctx.Cache{Name: "password", Value: m.Confx("password", arg, 2), Help: "密码"}, "password": &ctx.Cache{Name: "password", Value: m.Confx("password", arg, 2), Help: "密码"},
"address": &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 3), Help: "地址"}, "address": &ctx.Cache{Name: "address", Value: m.Confx("address", arg, 3), Help: "地址"},
"protocol": &ctx.Cache{Name: "protocol(tcp)", Value: m.Confx("protocol", arg, 4), Help: "协议"}, "protocol": &ctx.Cache{Name: "protocol(tcp)", Value: m.Confx("protocol", arg, 4), Help: "协议"},
"driver": &ctx.Cache{Name: "driver(mysql)", Value: m.Confx("driver", arg, 5), Help: "驱动"}, "driver": &ctx.Cache{Name: "driver(mysql)", Value: m.Confx("driver", arg, 5), Help: "驱动"},
"redis": &ctx.Cache{Name: "redis", Value: "", Help: "数据缓存"},
} }
c.Configs = map[string]*ctx.Config{ c.Configs = map[string]*ctx.Config{
"dbs": &ctx.Config{Name: "dbs", Value: []string{}, Help: "数据库"}, "dbs": &ctx.Config{Name: "dbs", Value: []string{}, Help: "数据库"},
@ -36,18 +37,17 @@ func (mdb *MDB) Spawn(m *ctx.Message, c *ctx.Context, arg ...string) ctx.Server
"offset": &ctx.Config{Name: "offset", Value: "0", Help: "偏移"}, "offset": &ctx.Config{Name: "offset", Value: "0", Help: "偏移"},
} }
s := new(MDB) return &MDB{Context: c}
s.Context = c
return s
} }
func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server { func (mdb *MDB) Begin(m *ctx.Message, arg ...string) ctx.Server {
return mdb return mdb
} }
func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool { func (mdb *MDB) Start(m *ctx.Message, arg ...string) bool {
db, e := sql.Open(m.Cap("driver"), fmt.Sprintf("%s:%s@%s(%s)/%s", m.Cap("username"), m.Cap("password"), m.Cap("protocol"), m.Cap("address"), m.Cap("database"))) if db, e := sql.Open(m.Cap("driver"), fmt.Sprintf("%s:%s@%s(%s)/%s", m.Cap("username"), m.Cap("password"),
m.Assert(e) m.Cap("protocol"), m.Cap("address"), m.Cap("database"))); m.Assert(e) {
mdb.DB = db
m.Log("info", "mdb open %s", m.Cap("stream", m.Cap("database"))) m.Log("info", "mdb open %s", m.Cap("stream", m.Cap("database")))
mdb.DB = db
}
return false return false
} }
func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool { func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
@ -57,16 +57,19 @@ func (mdb *MDB) Close(m *ctx.Message, arg ...string) bool {
var Index = &ctx.Context{Name: "mdb", Help: "数据中心", var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
Caches: map[string]*ctx.Cache{ Caches: map[string]*ctx.Cache{
"nsource": &ctx.Cache{Name: "nsource", Value: "0", Help: "已打开数据库的数量"}, "nsource": &ctx.Cache{Name: "nsource", Value: "0", Help: "已打开数据库的数量"},
"redis": &ctx.Cache{Name: "redis", Value: "", Help: "服务地址"},
}, },
Configs: map[string]*ctx.Config{ Configs: map[string]*ctx.Config{
"database": &ctx.Config{Name: "database", Value: "demo", Help: "默认数据库"}, "database": &ctx.Config{Name: "database", Value: "demo", Help: "默认数据库"},
"username": &ctx.Config{Name: "username", Value: "demo", Help: "默认账户"}, "username": &ctx.Config{Name: "username", Value: "demo", Help: "默认账户"},
"password": &ctx.Config{Name: "password", Value: "demo", Help: "默认密码"}, "password": &ctx.Config{Name: "password", Value: "demo", Help: "默认密码"},
"address": &ctx.Config{Name: "address", Value: ":6379", Help: "默认地址"},
"protocol": &ctx.Config{Name: "protocol(tcp)", Value: "tcp", Help: "默认协议"}, "protocol": &ctx.Config{Name: "protocol(tcp)", Value: "tcp", Help: "默认协议"},
"address": &ctx.Config{Name: "address", Value: "", Help: "默认地址"},
"driver": &ctx.Config{Name: "driver(mysql)", Value: "mysql", Help: "默认驱动"}, "driver": &ctx.Config{Name: "driver(mysql)", Value: "mysql", Help: "默认驱动"},
"ktv": &ctx.Config{Name: "ktv", Value: map[string]interface{}{
"conf": map[string]interface{}{"expire": "24h"}, "data": map[string]interface{}{},
}, Help: "缓存数据"},
"temp": &ctx.Config{Name: "temp", Value: map[string]interface{}{}, Help: "缓存数据"}, "temp": &ctx.Config{Name: "temp", Value: map[string]interface{}{}, Help: "缓存数据"},
"temp_view": &ctx.Config{Name: "temp_view", Value: map[string]interface{}{}, Help: "缓存数据"}, "temp_view": &ctx.Config{Name: "temp_view", Value: map[string]interface{}{}, Help: "缓存数据"},
"temp_expire": &ctx.Config{Name: "temp_expire(s)", Value: "3000", Help: "缓存数据"}, "temp_expire": &ctx.Config{Name: "temp_expire(s)", Value: "3000", Help: "缓存数据"},
@ -96,102 +99,11 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
"base": []interface{}{"key", "create_time", "type", "name", "model", "value"}, "base": []interface{}{"key", "create_time", "type", "name", "model", "value"},
"full": []interface{}{"key", "create_time", "access_time", "type", "name", "model", "value", "view", "data", "ship"}, "full": []interface{}{"key", "create_time", "access_time", "type", "name", "model", "value", "view", "data", "ship"},
}, Help: "数据视图"}, }, Help: "数据视图"},
"ktv": &ctx.Config{Name: "ktv", Value: map[string]interface{}{
"conf": map[string]interface{}{"expire": "24h"}, "data": map[string]interface{}{},
}, Help: "缓存数据"},
}, },
Commands: map[string]*ctx.Command{ Commands: map[string]*ctx.Command{
"ktv": &ctx.Command{Name: "ktv", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
now := kit.Int(m.Time("stamp"))
m.Confm("ktv", "data", func(key string, value map[string]interface{}) {
m.Push("key", key)
m.Push("expire", kit.Int(value["expire"])-now)
m.Push("value", value["value"])
})
m.Table()
return
}
if len(arg) == 1 {
if m.Confi("ktv", []string{"data", arg[0], "expire"}) < kit.Int(m.Time("stamp")) {
m.Conf("ktv", []string{"data", arg[0]}, "")
}
m.Echo(m.Conf("ktv", []string{"data", arg[0], "value"}))
return
}
m.Confv("ktv", []string{"data", arg[0]}, map[string]interface{}{
"expire": m.Time(kit.Select(m.Conf("ktv", "conf.expire"), arg, 2), "stamp"),
"value": arg[1],
})
m.Echo(arg[1])
return
}},
"redis": &ctx.Command{Name: "redis open address [protocol]", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) {
switch arg[0] {
case "open":
mdb.conn, e = redis.Dial("tcp", m.Cap("redis", arg[1]), redis.DialKeepAlive(time.Second*10))
default:
if mdb.conn == nil {
m.Echo("not open")
break
}
if mdb.conn.Err() != nil {
mdb.conn, e = redis.Dial("tcp", m.Cap("redis"), redis.DialKeepAlive(time.Second*10))
}
args := []interface{}{}
for _, v := range arg[1:] {
args = append(args, v)
}
res, err := mdb.conn.Do(arg[0], args...)
m.Assert(err)
switch val := res.(type) {
case redis.Error:
m.Echo("%v", val)
case []interface{}:
for i, v := range val {
m.Add("append", "index", i)
m.Add("append", "value", v)
}
m.Table()
default:
str := kit.Format(res)
var data interface{}
if json.Unmarshal([]byte(str), &data) == nil {
m.Echo(kit.Formats(data))
} else {
m.Echo(str)
}
}
}
}
return
}},
"open": &ctx.Command{Name: "open [database [username [password [address [protocol [driver]]]]]]", "open": &ctx.Command{Name: "open [database [username [password [address [protocol [driver]]]]]]",
Help: "打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型", Help: "打开数据库, database: 数据库名, username: 用户名, password: 密码, address: 服务地址, protocol: 服务协议, driver: 数据库类型",
Form: map[string]int{"dbname": 1, "dbhelp": 1}, Form: map[string]int{"dbname": 1, "dbhelp": 1}, Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
switch len(arg) {
case 0:
m.Auto("", fmt.Sprintf("database(%s)", m.Conf("database")), "数据库")
case 1:
m.Auto("", fmt.Sprintf("username(%s)", m.Conf("username")), "账号")
case 2:
m.Auto("", fmt.Sprintf("password(%s)", m.Conf("password")), "密码")
case 3:
m.Auto("", fmt.Sprintf("address(%s)", m.Conf("address")), "地址")
case 4:
m.Auto("", fmt.Sprintf("protocol(%s)", m.Conf("protocol")), "协议")
case 5:
m.Auto("", fmt.Sprintf("driver(%s)", m.Conf("driver")), "驱动")
default:
m.Auto("", "[dbname name]", "模块名")
m.Auto("", "[dbhelp help]", "帮助文档")
}
return true
},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
m.Start(kit.Select(fmt.Sprintf("db%d", m.Capi("nsource", 1)), m.Option("dbname")), m.Start(kit.Select(fmt.Sprintf("db%d", m.Capi("nsource", 1)), m.Option("dbname")),
kit.Select("数据源", m.Option("dbhelp")), arg...) kit.Select("数据源", m.Option("dbhelp")), arg...)
return return
@ -203,16 +115,13 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
which = append(which, v) which = append(which, v)
} }
ret, e := mdb.Exec(arg[0], which...) if ret, e := mdb.Exec(arg[0], which...); m.Assert(e) {
m.Assert(e) id, _ := ret.LastInsertId()
id, e := ret.LastInsertId() n, _ := ret.RowsAffected()
m.Assert(e)
n, e := ret.RowsAffected()
m.Assert(e)
m.Log("info", "last(%s) nrow(%s)", m.Append("last", id), m.Append("nrow", n)) m.Log("info", "last(%s) nrow(%s)", m.Append("last", id), m.Append("nrow", n))
m.Echo("%d", n) m.Echo("%d", n)
} }
}
return return
}}, }},
"query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { "query": &ctx.Command{Name: "query sql [arg]", Help: "查询数据库, sql: SQL语句, arg: 查询参数", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
@ -222,12 +131,9 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
which = append(which, v) which = append(which, v)
} }
rows, e := mdb.Query(arg[0], which...) if rows, e := mdb.Query(arg[0], which...); m.Assert(e) {
m.Assert(e)
defer rows.Close() defer rows.Close()
if cols, e := rows.Columns(); m.Assert(e) {
cols, e := rows.Columns()
m.Assert(e)
num := len(cols) num := len(cols)
for rows.Next() { for rows.Next() {
@ -239,16 +145,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
rows.Scan(ptrs...) rows.Scan(ptrs...)
for i, k := range cols { for i, k := range cols {
switch b := vals[i].(type) { m.Push(k, vals[i])
case nil:
m.Add("append", k, "")
case []byte:
m.Add("append", k, string(b))
case int64:
m.Add("append", k, fmt.Sprintf("%d", b))
default:
m.Add("append", k, fmt.Sprintf("%v", b))
}
} }
} }
@ -259,21 +156,61 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
} }
m.Table() m.Table()
} }
}
}
return
}},
"redis": &ctx.Command{Name: "redis [open address]|[cmd...]", Help: "缓存数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if mdb, ok := m.Target().Server.(*MDB); m.Assert(ok) {
switch arg[0] {
case "open":
if mdb.conn, e = redis.Dial("tcp", m.Cap("redis", arg[1]), redis.DialKeepAlive(time.Second*10)); m.Assert(e) {
m.Log("info", "redis: %v", arg[1])
}
default:
if mdb.conn == nil || mdb.conn.Err() != nil {
if m.Caps("redis") {
m.Cmd("mdb.redis", "open", m.Cap("redis"))
} else {
m.Echo("not open")
break
}
}
args := []interface{}{}
for _, v := range arg[1:] {
args = append(args, v)
}
if res, err := mdb.conn.Do(arg[0], args...); m.Assert(err) {
switch val := res.(type) {
case redis.Error:
m.Echo("%v", val)
case []interface{}:
for i, v := range val {
m.Add("append", "index", i)
m.Add("append", "value", v)
}
m.Table()
default:
var data interface{}
if str := kit.Format(res); json.Unmarshal([]byte(str), &data) == nil {
m.Echo(kit.Formats(data))
} else {
m.Echo(str)
}
}
}
}
}
return return
}}, }},
"db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库", "db": &ctx.Command{Name: "db [which]", Help: "查看或选择数据库", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
if len(arg) == 0 {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show databases").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}
})
}
return true
},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 { if len(arg) == 0 {
m.Cmdy(".query", "show databases").Table() m.Cmdy(".query", "show databases").Table()
return return
@ -283,23 +220,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
m.Echo(m.Cap("database", arg[0])) m.Echo(m.Cap("database", arg[0]))
return return
}}, }},
"tab": &ctx.Command{Name: "tab [which [field]]", Help: "查看关系表which: 表名, field: 字段名", "tab": &ctx.Command{Name: "tab [which [field]]", Help: "查看关系表which: 表名, field: 字段名", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
switch len(arg) {
case 0:
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}
})
case 1:
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", fmt.Sprintf("desc %s", arg[0])).Table(func(line map[string]string) {
m.Auto(line["Field"], line["Type"], line["Default"])
})
}
return true
},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
switch len(arg) { switch len(arg) {
case 0: case 0:
m.Cmdy(".query", "show tables").Table() m.Cmdy(".query", "show tables").Table()
@ -311,31 +232,7 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
return return
}}, }},
"show": &ctx.Command{Name: "show table fields...", Help: "查询数据, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段", "show": &ctx.Command{Name: "show table fields...", Help: "查询数据, table: 表名, fields: 字段, where: 查询条件, group: 聚合字段, order: 排序字段",
Form: map[string]int{"where": 1, "eq": 2, "like": 2, "in": 2, "begin": 2, "group": 1, "order": 1, "desc": 0, "limit": 1, "offset": 1, "other": -1}, Form: map[string]int{"where": 1, "eq": 2, "in": 2, "like": 2, "begin": 2, "group": 1, "order": 1, "desc": 0, "limit": 1, "offset": 1, "other": -1},
Auto: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) bool {
if len(arg) == 0 {
m.Put("option", "bio.cmd", "").Spawn().Cmd("query", "show tables").Table(func(line map[string]string) {
for _, v := range line {
m.Auto(v, "", "")
}
})
return true
}
m.Auto("where", "stmt", "条件语句")
m.Auto("eq", "field value", "条件语句")
m.Auto("in", "field value", "条件语句")
m.Auto("like", "field value", "条件语句")
m.Auto("begin", "field value", "条件语句")
m.Auto("group", "field", "聚合")
m.Auto("order", "field", "排序")
m.Auto("desc", "", "降序")
m.Auto("limit", "10", "分页")
m.Auto("offset", "0", "偏移")
m.Auto("other", "stmt", "其它")
return true
},
Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 { if len(arg) == 0 {
m.Cmdy(".query", "show tables") m.Cmdy(".query", "show tables")
@ -407,17 +304,43 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
values = append(values, fmt.Sprintf("%s='%s'", arg[i], arg[i+1])) values = append(values, fmt.Sprintf("%s='%s'", arg[i], arg[i+1]))
} }
stmt := []string{fmt.Sprintf("update %s", arg[0])} stmt := []string{"update", arg[0]}
stmt = append(stmt, "set", strings.Join(values, ",")) stmt = append(stmt, "set", strings.Join(values, ","))
stmt = append(stmt, fmt.Sprintf("where %s", arg[1])) stmt = append(stmt, "where", arg[1])
m.Cmd(".exec", strings.Join(stmt, " ")) m.Cmd(".exec", strings.Join(stmt, " "))
m.Cmdy("show", arg[0], fields, "where", arg[1])
m.Cmdy(".show", arg[0], fields, "where", arg[1])
} }
return return
}}, }},
"temp": &ctx.Command{Name: "temp [type [meta [data]]] [tid [node|ship|data] [chain... [select ...]]]", Form: map[string]int{"select": -1, "limit": 1}, Help: "缓存数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) { "ktv": &ctx.Command{Name: "ktv", Help: "", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) == 0 {
now := kit.Int(m.Time("stamp"))
m.Confm("ktv", "data", func(key string, value map[string]interface{}) {
m.Push("key", key)
m.Push("expire", kit.Int(value["expire"])-now)
m.Push("value", value["value"])
})
m.Table()
return
}
if len(arg) == 1 {
if m.Confi("ktv", []string{"data", arg[0], "expire"}) < kit.Int(m.Time("stamp")) {
m.Conf("ktv", []string{"data", arg[0]}, "")
}
m.Echo(m.Conf("ktv", []string{"data", arg[0], "value"}))
return
}
m.Confv("ktv", []string{"data", arg[0]}, map[string]interface{}{
"expire": m.Time(kit.Select(m.Conf("ktv", "conf.expire"), arg, 2), "stamp"),
"value": arg[1],
})
m.Echo(arg[1])
return
}},
"temp": &ctx.Command{Name: "temp [type [meta [data]]] [tid [node|ship|data] [chain... [select ...]]]",
Form: map[string]int{"select": -1, "limit": 1}, Help: "缓存数据", Hand: func(m *ctx.Message, c *ctx.Context, key string, arg ...string) (e error) {
if len(arg) > 0 && arg[0] == "check" { if len(arg) > 0 && arg[0] == "check" {
h := "" h := ""
for i := 1; i < len(arg)-1; i += 2 { for i := 1; i < len(arg)-1; i += 2 {
@ -873,7 +796,5 @@ var Index = &ctx.Context{Name: "mdb", Help: "数据中心",
} }
func init() { func init() {
mdb := &MDB{} ctx.Index.Register(Index, &MDB{Context: Index})
mdb.Context = Index
ctx.Index.Register(Index, mdb)
} }