Commit e23d2a79 authored by vipwzw's avatar vipwzw Committed by 33cn

add table query

parent e650737b
...@@ -8,6 +8,9 @@ function Init(context) { ...@@ -8,6 +8,9 @@ function Init(context) {
return this.kvc.receipt() return this.kvc.receipt()
} }
var MIN_WAIT_BLOCK = 2
var RAND_MAX = 10
function ExecInit(execthis) { function ExecInit(execthis) {
execthis.acc = new account(this.kvc, "coins", "bty") execthis.acc = new account(this.kvc, "coins", "bty")
} }
...@@ -24,13 +27,13 @@ Exec.prototype.NewGame = function(args) { ...@@ -24,13 +27,13 @@ Exec.prototype.NewGame = function(args) {
game.status = 1 //open game.status = 1 //open
//最大值是 9000万,否则js到 int 会溢出 //最大值是 9000万,否则js到 int 会溢出
if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) { if (game.bet < 10 * COINS || game.bet > 10000000 * COINS) {
throw new Error("bet low than 10 or hight than 10000000") throwerr("bet low than 10 or hight than 10000000")
} }
var err = this.acc.execFrozen(this.name, this.context.from, game.bet) var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err) throwerr(err)
this.kvc.add(game.id, game) this.kvc.add(game.id, game)
this.kvc.addlog(game) this.kvc.addlog(game)
return this.kvc.receipt() return this.kvc.receipt()
} }
Exec.prototype.Guess = function(args) { Exec.prototype.Guess = function(args) {
...@@ -41,19 +44,19 @@ Exec.prototype.Guess = function(args) { ...@@ -41,19 +44,19 @@ Exec.prototype.Guess = function(args) {
match.addr = this.context.from match.addr = this.context.from
var game = this.kvc.get(match.gameid) var game = this.kvc.get(match.gameid)
if (!game) { if (!game) {
throw new Error("game id not found") throwerr("game id not found")
} }
if (game.status != 1) { if (game.status != 1) {
throw new Error("game status not open") throwerr("game status not open")
} }
if (match.bet < 1 * COINS || match.bet > game.bet/10) { if (match.bet < 1 * COINS || match.bet > game.bet / RAND_MAX) {
throw new Error("match bet litte than 1 or big than game.bet/10") throwerr("match bet litte than 1 or big than game.bet/10")
} }
var err = this.acc.execFrozen(this.name, this.context.from, game.bet) var err = this.acc.execFrozen(this.name, this.context.from, game.bet)
throwerr(err) throwerr(err)
this.kvc.add(match.id, match) this.kvc.add(match.id, match)
this.kvc.addlog(match) this.kvc.addlog(match)
return this.kvc.receipt() return this.kvc.receipt()
} }
Exec.prototype.CloseGame = function(args) { Exec.prototype.CloseGame = function(args) {
...@@ -67,7 +70,7 @@ Exec.prototype.CloseGame = function(args) { ...@@ -67,7 +70,7 @@ Exec.prototype.CloseGame = function(args) {
matches = [] matches = []
} }
var n = -1 var n = -1
for (var i = 0; i < 10; i ++) { for (var i = 0; i < RAND_MAX; i ++) {
if (sha256(args.randstr + i) == game.randhash) { if (sha256(args.randstr + i) == game.randhash) {
n = i n = i
} }
...@@ -75,8 +78,9 @@ Exec.prototype.CloseGame = function(args) { ...@@ -75,8 +78,9 @@ Exec.prototype.CloseGame = function(args) {
if (n == -1) { if (n == -1) {
throwerr("err rand str") throwerr("err rand str")
} }
if (this.context.height - game.height < 10) { //必须可以让用户可以有一个区块的竞猜时间
throwerr("close game must wait 10 block") if (this.context.height - game.height < MIN_WAIT_BLOCK) {
throwerr("close game must wait 2 block")
} }
for (var i = 0; i < matches.length; i++) { for (var i = 0; i < matches.length; i++) {
var match = matches[i] var match = matches[i]
...@@ -95,11 +99,11 @@ Exec.prototype.CloseGame = function(args) { ...@@ -95,11 +99,11 @@ Exec.prototype.CloseGame = function(args) {
game.status = 2 game.status = 2
this.kvc.add(game.id, game) this.kvc.add(game.id, game)
this.kvc.addlog(game) this.kvc.addlog(game)
return this.kvc.receipt() return this.kvc.receipt()
} }
function win(this, game, match) { function win(this, game, match) {
var amount = 9 * match.bet var amount = (RAND_MAX - 1) * match.bet
if (game.bet - amount < 0) { if (game.bet - amount < 0) {
amount = game.bet amount = game.bet
} }
...@@ -145,28 +149,28 @@ Exec.prototype.ForceCloseGame = function(args) { ...@@ -145,28 +149,28 @@ Exec.prototype.ForceCloseGame = function(args) {
game.status = 2 game.status = 2
this.kvc.add(game.id, game) this.kvc.add(game.id, game)
this.kvc.addlog(game) this.kvc.addlog(game)
return this.kvc.receipt() return this.kvc.receipt()
} }
ExecLocal.prototype.NewGame = function(args) { ExecLocal.prototype.NewGame = function(args) {
var local = new MatchGameTable(this.kvc) var local = new MatchGameTable(this.kvc)
local.add(this.logs) local.add(this.logs)
local.table.save() local.table.save()
return this.kvc.receipt() return this.kvc.receipt()
} }
ExecLocal.prototype.Guess = function(args) { ExecLocal.prototype.Guess = function(args) {
var local = new MatchGameTable(this.kvc) var local = new MatchGameTable(this.kvc)
local.add(this.logs) local.add(this.logs)
local.table.save() local.table.save()
return this.kvc.receipt() return this.kvc.receipt()
} }
ExecLocal.prototype.CloseGame = function(args) { ExecLocal.prototype.CloseGame = function(args) {
var local = new MatchGameTable(this.kvc) var local = new MatchGameTable(this.kvc)
local.add(this.logs) local.add(this.logs)
local.table.save() local.table.save()
return this.kvc.receipt() return this.kvc.receipt()
} }
ExecLocal.prototype.ForceCloseGame = function(args) { ExecLocal.prototype.ForceCloseGame = function(args) {
...@@ -188,7 +192,6 @@ game.id -> primary ...@@ -188,7 +192,6 @@ game.id -> primary
match.gameid -> fk match.gameid -> fk
match.id -> primary match.id -> primary
*/ */
function GameLocalTable(kvc) { function GameLocalTable(kvc) {
this.config = { this.config = {
"#tablename" : "game", "#tablename" : "game",
......
...@@ -2,6 +2,7 @@ package executor ...@@ -2,6 +2,7 @@ package executor
import ( import (
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"strings" "strings"
"sync" "sync"
...@@ -121,9 +122,9 @@ func getTable(id int64) (*table.Table, error) { ...@@ -121,9 +122,9 @@ func getTable(id int64) (*table.Table, error) {
return nil, types.ErrNotFound return nil, types.ErrNotFound
} }
func getSaver(id int64) (saver, error) { func getTabler(id int64) (tabler, error) {
if value, ok := globalTableHandle.Load(id); ok { if value, ok := globalTableHandle.Load(id); ok {
return value.(saver), nil return value.(tabler), nil
} }
return nil, types.ErrNotFound return nil, types.ErrNotFound
} }
...@@ -135,6 +136,24 @@ func registerTableFunc(vm *otto.Otto) { ...@@ -135,6 +136,24 @@ func registerTableFunc(vm *otto.Otto) {
tableCloseFunc(vm) tableCloseFunc(vm)
tableSave(vm) tableSave(vm)
tableJoinFunc(vm) tableJoinFunc(vm)
tableQueryFunc(vm)
tableGetFunc(vm)
tableJoinKeyFunc(vm)
}
func tableJoinKeyFunc(vm *otto.Otto) {
vm.Set("table_joinkey", func(call otto.FunctionCall) otto.Value {
left, err := call.Argument(0).ToString()
if err != nil {
return errReturn(vm, err)
}
right, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
key := table.JoinKey([]byte(left), []byte(right))
return okReturn(vm, string(key))
})
} }
func tableAddFunc(vm *otto.Otto) { func tableAddFunc(vm *otto.Otto) {
...@@ -203,7 +222,37 @@ func tableDelFunc(vm *otto.Otto) { ...@@ -203,7 +222,37 @@ func tableDelFunc(vm *otto.Otto) {
}) })
} }
type saver interface { func tableGetFunc(vm *otto.Otto) {
vm.Set("table_get", func(call otto.FunctionCall) otto.Value {
id, err := call.Argument(0).ToInteger()
if err != nil {
return errReturn(vm, err)
}
tab, err := getTabler(id)
if err != nil {
return errReturn(vm, err)
}
key, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
row, err := call.Argument(2).ToString()
if err != nil {
return errReturn(vm, err)
}
meta := tab.GetMeta()
meta.SetPayload(&jsproto.JsLog{Data: row})
result, err := meta.Get(key)
if err != nil {
return errReturn(vm, err)
}
return okReturn(vm, string(result))
})
}
type tabler interface {
GetMeta() table.RowMeta
ListIndex(indexName string, prefix []byte, primaryKey []byte, count, direction int32) (rows []*table.Row, err error)
Save() (kvs []*types.KeyValue, err error) Save() (kvs []*types.KeyValue, err error)
} }
...@@ -213,7 +262,7 @@ func tableSave(vm *otto.Otto) { ...@@ -213,7 +262,7 @@ func tableSave(vm *otto.Otto) {
if err != nil { if err != nil {
return errReturn(vm, err) return errReturn(vm, err)
} }
tab, err := getSaver(id) tab, err := getTabler(id)
if err != nil { if err != nil {
return errReturn(vm, err) return errReturn(vm, err)
} }
...@@ -239,6 +288,86 @@ func tableCloseFunc(vm *otto.Otto) { ...@@ -239,6 +288,86 @@ func tableCloseFunc(vm *otto.Otto) {
}) })
} }
func tableQueryFunc(vm *otto.Otto) {
vm.Set("table_query", func(call otto.FunctionCall) otto.Value {
id, err := call.Argument(0).ToInteger()
if err != nil {
return errReturn(vm, err)
}
tab, err := getTabler(id)
if err != nil {
return errReturn(vm, err)
}
//参数
//List(indexName string, data types.Message, primaryKey []byte, count, direction int32) (rows []*Row, err error)
indexName, err := call.Argument(1).ToString()
if err != nil {
return errReturn(vm, err)
}
prefix, err := call.Argument(2).ToString()
if err != nil {
return errReturn(vm, err)
}
primaryKey, err := call.Argument(3).ToString()
if err != nil {
return errReturn(vm, err)
}
count, err := call.Argument(4).ToInteger()
if err != nil {
return errReturn(vm, err)
}
direction, err := call.Argument(5).ToInteger()
if err != nil {
return errReturn(vm, err)
}
bprefix := []byte(prefix)
if prefix == "" {
bprefix = nil
}
bprimaryKey := []byte(primaryKey)
if primaryKey == "" {
bprimaryKey = nil
}
rows, err := tab.ListIndex(indexName, bprefix, bprimaryKey, int32(count), int32(direction))
if err != nil {
return errReturn(vm, err)
}
_, isjoin := tab.(*table.JoinTable)
querylist := make([]*otto.Object, len(rows))
for i := 0; i < len(rows); i++ {
if isjoin {
joindata, ok := rows[i].Data.(*table.JoinData)
if !ok {
return errReturn(vm, errors.New("jointable has no joindata"))
}
leftdata, ok := joindata.Left.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("leftdata is not JsLog"))
}
rightdata, ok := joindata.Right.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("rightdata is not jslog"))
}
obj := newObject(vm).setValue("left", leftdata.Data)
obj.setValue("right", rightdata.Data)
querylist[i] = obj.object()
} else {
leftdata, ok := rows[i].Data.(*jsproto.JsLog)
if !ok {
return errReturn(vm, errors.New("data is not JsLog"))
}
obj := newObject(vm).setValue("left", leftdata.Data)
querylist[i] = obj.object()
}
}
retvalue, err := vm.ToValue(querylist)
if err != nil {
return errReturn(vm, err)
}
return retvalue
})
}
func tableJoinFunc(vm *otto.Otto) { func tableJoinFunc(vm *otto.Otto) {
vm.Set("new_join_table", func(call otto.FunctionCall) otto.Value { vm.Set("new_join_table", func(call otto.FunctionCall) otto.Value {
left, err := call.Argument(0).ToInteger() left, err := call.Argument(0).ToInteger()
......
...@@ -312,6 +312,16 @@ func (table *Table) getPrimaryFromData(data types.Message) (primaryKey []byte, e ...@@ -312,6 +312,16 @@ func (table *Table) getPrimaryFromData(data types.Message) (primaryKey []byte, e
return return
} }
//ListIndex list table index
func (table *Table) ListIndex(indexName string, prefix []byte, primaryKey []byte, count, direction int32) (rows []*Row, err error) {
kvdb, ok := table.kvdb.(db.KVDB)
if !ok {
return nil, errors.New("list only support KVDB interface")
}
query := &Query{table: table, kvdb: kvdb}
return query.ListIndex(indexName, prefix, primaryKey, count, direction)
}
//Replace 如果有重复的,那么替换 //Replace 如果有重复的,那么替换
func (table *Table) Replace(data types.Message) error { func (table *Table) Replace(data types.Message) error {
if err := table.checkIndex(data); err != nil { if err := table.checkIndex(data); err != nil {
...@@ -602,8 +612,15 @@ func (table *Table) getModify(row, oldrow *Row, index string) ([]byte, []byte, b ...@@ -602,8 +612,15 @@ func (table *Table) getModify(row, oldrow *Row, index string) ([]byte, []byte, b
return indexkey, oldkey, true, nil return indexkey, oldkey, true, nil
} }
//GetQuery 获取查询结构 //GetQuery 获取查询结构(允许传入 kvdb 为nil)
func (table *Table) GetQuery(kvdb db.KVDB) *Query { func (table *Table) GetQuery(kvdb db.KVDB) *Query {
if kvdb == nil {
var ok bool
kvdb, ok = table.kvdb.(db.KVDB)
if !ok {
return nil
}
}
return &Query{table: table, kvdb: kvdb} return &Query{table: table, kvdb: kvdb}
} }
...@@ -611,6 +628,11 @@ func (table *Table) getMeta() RowMeta { ...@@ -611,6 +628,11 @@ func (table *Table) getMeta() RowMeta {
return table.meta return table.meta
} }
//GetMeta 获取meta
func (table *Table) GetMeta() RowMeta {
return table.getMeta()
}
func (table *Table) getOpt() *Option { func (table *Table) getOpt() *Option {
return table.opt return table.opt
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment