Enable parameters in LIVE queries
This commit is contained in:
parent
92ecba9154
commit
e3c7aacd66
8 changed files with 1225 additions and 1138 deletions
104
db/db.gen.go
104
db/db.gen.go
|
@ -12,25 +12,19 @@ import (
|
|||
|
||||
const (
|
||||
// ----- content types ----
|
||||
codecSelferCcUTF82764 = 1
|
||||
codecSelferCcRAW2764 = 0
|
||||
codecSelferCcUTF82423 = 1
|
||||
codecSelferCcRAW2423 = 0
|
||||
// ----- value types used ----
|
||||
codecSelferValueTypeArray2764 = 10
|
||||
codecSelferValueTypeMap2764 = 9
|
||||
// ----- containerStateValues ----
|
||||
codecSelferKcontainerMapKey2764 = 2
|
||||
codecSelferKcontainerMapValue2764 = 3
|
||||
codecSelferKcontainerMapEnd2764 = 4
|
||||
codecSelferKcontainerArrayElem2764 = 6
|
||||
codecSelferKcontainerArrayEnd2764 = 7
|
||||
codecSelferValueTypeArray2423 = 10
|
||||
codecSelferValueTypeMap2423 = 9
|
||||
)
|
||||
|
||||
var (
|
||||
codecSelferBitsize2764 = uint8(reflect.TypeOf(uint(0)).Bits())
|
||||
errCodecSelferOnlyMapOrArrayEncodeToStruct2764 = errors.New(`only encoded map or array can be decoded into a struct`)
|
||||
codecSelferBitsize2423 = uint8(reflect.TypeOf(uint(0)).Bits())
|
||||
errCodecSelferOnlyMapOrArrayEncodeToStruct2423 = errors.New(`only encoded map or array can be decoded into a struct`)
|
||||
)
|
||||
|
||||
type codecSelfer2764 struct{}
|
||||
type codecSelfer2423 struct{}
|
||||
|
||||
func init() {
|
||||
if codec1978.GenVersion != 8 {
|
||||
|
@ -44,7 +38,7 @@ func init() {
|
|||
}
|
||||
|
||||
func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
if x == nil {
|
||||
|
@ -53,7 +47,8 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
yym1 := z.EncBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(x) {
|
||||
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||
z.EncExtension(x, yyxt1)
|
||||
} else {
|
||||
yysep2 := !z.EncBinary()
|
||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||
|
@ -84,21 +79,21 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
_ = yym4
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Time))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Time))
|
||||
}
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, "")
|
||||
r.EncodeString(codecSelferCcUTF82423, "")
|
||||
}
|
||||
} else {
|
||||
if yyq2[0] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `time`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `time`)
|
||||
r.WriteMapElemValue()
|
||||
yym5 := z.EncBinary()
|
||||
_ = yym5
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Time))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Time))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -109,21 +104,21 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Status))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Status))
|
||||
}
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, "")
|
||||
r.EncodeString(codecSelferCcUTF82423, "")
|
||||
}
|
||||
} else {
|
||||
if yyq2[1] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `status`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `status`)
|
||||
r.WriteMapElemValue()
|
||||
yym8 := z.EncBinary()
|
||||
_ = yym8
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Status))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Status))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -134,21 +129,21 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
_ = yym10
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Detail))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Detail))
|
||||
}
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, "")
|
||||
r.EncodeString(codecSelferCcUTF82423, "")
|
||||
}
|
||||
} else {
|
||||
if yyq2[2] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `detail`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `detail`)
|
||||
r.WriteMapElemValue()
|
||||
yym11 := z.EncBinary()
|
||||
_ = yym11
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Detail))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Detail))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -171,7 +166,7 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
} else {
|
||||
if yyq2[3] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `result`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `result`)
|
||||
r.WriteMapElemValue()
|
||||
if x.Result == nil {
|
||||
r.EncodeNil()
|
||||
|
@ -195,23 +190,24 @@ func (x *Response) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
}
|
||||
|
||||
func (x *Response) CodecDecodeSelf(d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
yym1 := z.DecBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(x) {
|
||||
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||
z.DecExtension(x, yyxt1)
|
||||
} else {
|
||||
yyct2 := r.ContainerType()
|
||||
if yyct2 == codecSelferValueTypeMap2764 {
|
||||
if yyct2 == codecSelferValueTypeMap2423 {
|
||||
yyl2 := r.ReadMapStart()
|
||||
if yyl2 == 0 {
|
||||
r.ReadMapEnd()
|
||||
} else {
|
||||
x.codecDecodeSelfFromMap(yyl2, d)
|
||||
}
|
||||
} else if yyct2 == codecSelferValueTypeArray2764 {
|
||||
} else if yyct2 == codecSelferValueTypeArray2423 {
|
||||
yyl2 := r.ReadArrayStart()
|
||||
if yyl2 == 0 {
|
||||
r.ReadArrayEnd()
|
||||
|
@ -219,13 +215,13 @@ func (x *Response) CodecDecodeSelf(d *codec1978.Decoder) {
|
|||
x.codecDecodeSelfFromArray(yyl2, d)
|
||||
}
|
||||
} else {
|
||||
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct2764)
|
||||
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct2423)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Response) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
|
||||
|
@ -302,7 +298,7 @@ func (x *Response) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
|||
}
|
||||
|
||||
func (x *Response) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj12 int
|
||||
|
@ -413,7 +409,7 @@ func (x *Response) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
|||
}
|
||||
|
||||
func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperEncoder(e)
|
||||
_, _, _ = h, z, r
|
||||
if x == nil {
|
||||
|
@ -422,7 +418,8 @@ func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
yym1 := z.EncBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.EncExt(x) {
|
||||
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||
z.EncExtension(x, yyxt1)
|
||||
} else {
|
||||
yysep2 := !z.EncBinary()
|
||||
yy2arr2 := z.EncBasicHandle().StructToArray
|
||||
|
@ -452,21 +449,21 @@ func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
_ = yym4
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Query))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Query))
|
||||
}
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, "")
|
||||
r.EncodeString(codecSelferCcUTF82423, "")
|
||||
}
|
||||
} else {
|
||||
if yyq2[0] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `query`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `query`)
|
||||
r.WriteMapElemValue()
|
||||
yym5 := z.EncBinary()
|
||||
_ = yym5
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Query))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Query))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -477,21 +474,21 @@ func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
_ = yym7
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Action))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Action))
|
||||
}
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, "")
|
||||
r.EncodeString(codecSelferCcUTF82423, "")
|
||||
}
|
||||
} else {
|
||||
if yyq2[1] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `action`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `action`)
|
||||
r.WriteMapElemValue()
|
||||
yym8 := z.EncBinary()
|
||||
_ = yym8
|
||||
if false {
|
||||
} else {
|
||||
r.EncodeString(codecSelferCcUTF82764, string(x.Action))
|
||||
r.EncodeString(codecSelferCcUTF82423, string(x.Action))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -514,7 +511,7 @@ func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
} else {
|
||||
if yyq2[2] {
|
||||
r.WriteMapElemKey()
|
||||
r.EncodeString(codecSelferCcUTF82764, `result`)
|
||||
r.EncodeString(codecSelferCcUTF82423, `result`)
|
||||
r.WriteMapElemValue()
|
||||
if x.Result == nil {
|
||||
r.EncodeNil()
|
||||
|
@ -538,23 +535,24 @@ func (x *Dispatch) CodecEncodeSelf(e *codec1978.Encoder) {
|
|||
}
|
||||
|
||||
func (x *Dispatch) CodecDecodeSelf(d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
yym1 := z.DecBinary()
|
||||
_ = yym1
|
||||
if false {
|
||||
} else if z.HasExtensions() && z.DecExt(x) {
|
||||
} else if yyxt1 := z.Extension(z.I2Rtid(x)); yyxt1 != nil {
|
||||
z.DecExtension(x, yyxt1)
|
||||
} else {
|
||||
yyct2 := r.ContainerType()
|
||||
if yyct2 == codecSelferValueTypeMap2764 {
|
||||
if yyct2 == codecSelferValueTypeMap2423 {
|
||||
yyl2 := r.ReadMapStart()
|
||||
if yyl2 == 0 {
|
||||
r.ReadMapEnd()
|
||||
} else {
|
||||
x.codecDecodeSelfFromMap(yyl2, d)
|
||||
}
|
||||
} else if yyct2 == codecSelferValueTypeArray2764 {
|
||||
} else if yyct2 == codecSelferValueTypeArray2423 {
|
||||
yyl2 := r.ReadArrayStart()
|
||||
if yyl2 == 0 {
|
||||
r.ReadArrayEnd()
|
||||
|
@ -562,13 +560,13 @@ func (x *Dispatch) CodecDecodeSelf(d *codec1978.Decoder) {
|
|||
x.codecDecodeSelfFromArray(yyl2, d)
|
||||
}
|
||||
} else {
|
||||
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct2764)
|
||||
panic(errCodecSelferOnlyMapOrArrayEncodeToStruct2423)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (x *Dispatch) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yys3Slc = z.DecScratchBuffer() // default slice to decode into
|
||||
|
@ -633,7 +631,7 @@ func (x *Dispatch) codecDecodeSelfFromMap(l int, d *codec1978.Decoder) {
|
|||
}
|
||||
|
||||
func (x *Dispatch) codecDecodeSelfFromArray(l int, d *codec1978.Decoder) {
|
||||
var h codecSelfer2764
|
||||
var h codecSelfer2423
|
||||
z, r := codec1978.GenHelperDecoder(d)
|
||||
_, _, _ = h, z, r
|
||||
var yyj10 int
|
||||
|
|
147
db/socket.go
147
db/socket.go
|
@ -15,6 +15,7 @@
|
|||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"context"
|
||||
|
@ -139,9 +140,9 @@ func (s *socket) flush() (err error) {
|
|||
|
||||
}
|
||||
|
||||
func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement) (err error) {
|
||||
func (s *socket) check(e *executor, ctx context.Context, ns, db, tb string) (err error) {
|
||||
|
||||
var tb *sql.DefineTableStatement
|
||||
var tbv *sql.DefineTableStatement
|
||||
|
||||
// If we are authenticated using DB, NS,
|
||||
// or KV permissions level, then we can
|
||||
|
@ -155,7 +156,7 @@ func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement)
|
|||
// otherwise, the scoped authentication
|
||||
// request can not do anything.
|
||||
|
||||
_, err = e.dbo.GetNS(stm.NS)
|
||||
_, err = e.dbo.GetNS(ns)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -164,7 +165,7 @@ func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement)
|
|||
// otherwise, the scoped authentication
|
||||
// request can not do anything.
|
||||
|
||||
_, err = e.dbo.GetDB(stm.NS, stm.DB)
|
||||
_, err = e.dbo.GetDB(ns, db)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -173,11 +174,18 @@ func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement)
|
|||
// otherwise, the scoped authentication
|
||||
// request can not do anything.
|
||||
|
||||
tb, err = e.dbo.GetTB(stm.NS, stm.DB, stm.What.TB)
|
||||
tbv, err = e.dbo.GetTB(ns, db, tb)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Once we have the table we reset the
|
||||
// context to DB level so that no other
|
||||
// embedded permissions are checked on
|
||||
// records within these permissions.
|
||||
|
||||
ctx = context.WithValue(ctx, ctxKeyKind, cnf.AuthDB)
|
||||
|
||||
// If the table does exist we then try
|
||||
// to process the relevant permissions
|
||||
// expression, but only if they don't
|
||||
|
@ -185,11 +193,11 @@ func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement)
|
|||
|
||||
var val interface{}
|
||||
|
||||
switch p := tb.Perms.(type) {
|
||||
switch p := tbv.Perms.(type) {
|
||||
case *sql.PermExpression:
|
||||
val, err = e.fetch(ctx, p.Select, ign)
|
||||
default:
|
||||
return &PermsError{table: stm.What.TB}
|
||||
return &PermsError{table: tb}
|
||||
}
|
||||
|
||||
// If we receive an 'ident failed' error
|
||||
|
@ -201,11 +209,11 @@ func (s *socket) check(e *executor, ctx context.Context, stm *sql.LiveStatement)
|
|||
|
||||
if err != queryIdentFailed {
|
||||
if val, ok := val.(bool); ok && !val {
|
||||
return &PermsError{table: stm.What.TB}
|
||||
return &PermsError{table: tb}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
|
@ -219,9 +227,24 @@ func (s *socket) deregister(id string) {
|
|||
|
||||
for id, stm := range s.lives {
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: stm.What.TB, LV: id}
|
||||
for _, w := range stm.What {
|
||||
|
||||
switch what := w.(type) {
|
||||
|
||||
case *sql.Table:
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, LV: id}
|
||||
txn.Clr(key.Encode())
|
||||
|
||||
case *sql.Ident:
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, LV: id}
|
||||
txn.Clr(key.Encode())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -231,20 +254,7 @@ func (s *socket) executeLive(e *executor, ctx context.Context, stm *sql.LiveStat
|
|||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
// Check that we are allowed to perform
|
||||
// the live query on the specified table
|
||||
// and if we can't then return an error
|
||||
// and don't save the live query.
|
||||
|
||||
err = s.check(e, ctx, stm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate a new uuid for this query,
|
||||
// which we will use to identify the
|
||||
// query when sending push messages
|
||||
// and when killing the query.
|
||||
// Generate a new query uuid.
|
||||
|
||||
stm.ID = uuid.New().String()
|
||||
|
||||
|
@ -252,16 +262,53 @@ func (s *socket) executeLive(e *executor, ctx context.Context, stm *sql.LiveStat
|
|||
|
||||
s.lives[stm.ID] = stm
|
||||
|
||||
// Add the live query to the database
|
||||
// under the relevant NS, DB, and TB.
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: stm.What.TB, LV: stm.ID}
|
||||
_, err = e.dbo.Put(0, key.Encode(), stm.Encode())
|
||||
|
||||
// Return the query id to the user.
|
||||
|
||||
out = append(out, stm.ID)
|
||||
|
||||
// Store the live query in the database layer.
|
||||
|
||||
for key, val := range stm.What {
|
||||
w, err := e.fetch(ctx, val, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stm.What[key] = w
|
||||
}
|
||||
|
||||
for _, w := range stm.What {
|
||||
|
||||
switch what := w.(type) {
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Can not execute LIVE query using value '%v'", what)
|
||||
|
||||
case *sql.Table:
|
||||
|
||||
if err = s.check(e, ctx, stm.NS, stm.DB, what.TB); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.TB, LV: stm.ID}
|
||||
if _, err = e.dbo.Put(0, key.Encode(), stm.Encode()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
case *sql.Ident:
|
||||
|
||||
if err = s.check(e, ctx, stm.NS, stm.DB, what.ID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
key := &keys.LV{KV: stm.KV, NS: stm.NS, DB: stm.DB, TB: what.ID, LV: stm.ID}
|
||||
if _, err = e.dbo.Put(0, key.Encode(), stm.Encode()); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
||||
|
@ -271,9 +318,26 @@ func (s *socket) executeKill(e *executor, ctx context.Context, stm *sql.KillStat
|
|||
s.mutex.Lock()
|
||||
defer s.mutex.Unlock()
|
||||
|
||||
// Get the specified query on this socket.
|
||||
// Remove the live query from the database layer.
|
||||
|
||||
if qry, ok := s.lives[stm.Name.ID]; ok {
|
||||
for key, val := range stm.What {
|
||||
w, err := e.fetch(ctx, val, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
stm.What[key] = w
|
||||
}
|
||||
|
||||
for _, w := range stm.What {
|
||||
|
||||
switch what := w.(type) {
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("Can not execute KILL query using value '%v'", what)
|
||||
|
||||
case string:
|
||||
|
||||
if qry, ok := s.lives[what]; ok {
|
||||
|
||||
// Delete the live query from the saved queries.
|
||||
|
||||
|
@ -281,9 +345,26 @@ func (s *socket) executeKill(e *executor, ctx context.Context, stm *sql.KillStat
|
|||
|
||||
// Delete the live query from the database layer.
|
||||
|
||||
key := &keys.LV{KV: qry.KV, NS: qry.NS, DB: qry.DB, TB: qry.What.TB, LV: qry.ID}
|
||||
for _, w := range qry.What {
|
||||
|
||||
switch what := w.(type) {
|
||||
|
||||
case *sql.Table:
|
||||
key := &keys.LV{KV: qry.KV, NS: qry.NS, DB: qry.DB, TB: what.TB, LV: qry.ID}
|
||||
_, err = e.dbo.Clr(key.Encode())
|
||||
|
||||
case *sql.Ident:
|
||||
key := &keys.LV{KV: qry.KV, NS: qry.NS, DB: qry.DB, TB: what.ID, LV: qry.ID}
|
||||
_, err = e.dbo.Clr(key.Encode())
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return
|
||||
|
|
2033
sql/ast.gen.go
2033
sql/ast.gen.go
File diff suppressed because it is too large
Load diff
|
@ -137,7 +137,7 @@ type LiveStatement struct {
|
|||
DB string `cork:"DB" codec:"DB"`
|
||||
Diff bool `cork:"diff" codec:"diff"`
|
||||
Expr Fields `cork:"expr" codec:"expr"`
|
||||
What *Table `cork:"what" codec:"what"`
|
||||
What Exprs `cork:"what" codec:"what"`
|
||||
Cond Expr `cork:"cond" codec:"cond"`
|
||||
}
|
||||
|
||||
|
@ -147,7 +147,7 @@ type KillStatement struct {
|
|||
KV string `cork:"KV" codec:"KV"`
|
||||
NS string `cork:"NS" codec:"NS"`
|
||||
DB string `cork:"DB" codec:"DB"`
|
||||
Name *Value `cork:"name" codec:"name"`
|
||||
What Exprs `cork:"what" codec:"what"`
|
||||
}
|
||||
|
||||
// SelectStatement represents a SQL SELECT statement.
|
||||
|
|
|
@ -18,7 +18,7 @@ func (p *parser) parseLiveStatement() (stmt *LiveStatement, err error) {
|
|||
|
||||
stmt = &LiveStatement{}
|
||||
|
||||
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthSC); err != nil {
|
||||
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthNO); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -42,7 +42,7 @@ func (p *parser) parseLiveStatement() (stmt *LiveStatement, err error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
if stmt.What, err = p.parseTable(); err != nil {
|
||||
if stmt.What, err = p.parseWhat(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -58,11 +58,11 @@ func (p *parser) parseKillStatement() (stmt *KillStatement, err error) {
|
|||
|
||||
stmt = &KillStatement{}
|
||||
|
||||
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthSC); err != nil {
|
||||
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthNO); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if stmt.Name, err = p.parseValue(); err != nil {
|
||||
if stmt.What, err = p.parseWhat(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
|
|
@ -2016,14 +2016,14 @@ func Test_Parse_Queries_Live(t *testing.T) {
|
|||
},
|
||||
{
|
||||
sql: `LIVE SELECT * FROM`,
|
||||
err: "Found `` but expected `table`",
|
||||
err: "Found `` but expected `expression`",
|
||||
},
|
||||
{
|
||||
sql: `LIVE SELECT * FROM person`,
|
||||
res: &Query{Statements: []Statement{&LiveStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Expr: []*Field{{Expr: &All{}, Field: "*"}},
|
||||
What: &Table{"person"},
|
||||
What: Exprs{&Ident{"person"}},
|
||||
}}},
|
||||
},
|
||||
{
|
||||
|
@ -2035,7 +2035,7 @@ func Test_Parse_Queries_Live(t *testing.T) {
|
|||
res: &Query{Statements: []Statement{&LiveStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Expr: []*Field{{Expr: &All{}, Field: "*"}},
|
||||
What: &Table{"person"},
|
||||
What: Exprs{&Ident{"person"}},
|
||||
Cond: &BinaryExpression{
|
||||
LHS: &Ident{"public"},
|
||||
Op: EQ,
|
||||
|
@ -2060,29 +2060,20 @@ func Test_Parse_Queries_Kill(t *testing.T) {
|
|||
var tests = []tester{
|
||||
{
|
||||
sql: `KILL`,
|
||||
err: "Found `` but expected `string`",
|
||||
},
|
||||
{
|
||||
sql: `KILL null`,
|
||||
err: "Found `null` but expected `string`",
|
||||
},
|
||||
{
|
||||
sql: `KILL 1`,
|
||||
err: "Found `1` but expected `string`",
|
||||
},
|
||||
{
|
||||
sql: `KILL 1.3000`,
|
||||
err: "Found `1.3000` but expected `string`",
|
||||
err: "Found `` but expected `expression`",
|
||||
},
|
||||
{
|
||||
sql: `KILL identifier`,
|
||||
err: "Found `identifier` but expected `string`",
|
||||
res: &Query{Statements: []Statement{&KillStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
What: Exprs{&Ident{"identifier"}},
|
||||
}}},
|
||||
},
|
||||
{
|
||||
sql: `KILL "identifier"`,
|
||||
res: &Query{Statements: []Statement{&KillStatement{
|
||||
KV: "*", NS: "*", DB: "*",
|
||||
Name: &Value{"identifier"},
|
||||
What: Exprs{&Value{"identifier"}},
|
||||
}}},
|
||||
},
|
||||
{
|
||||
|
|
|
@ -203,7 +203,7 @@ func (this LiveStatement) String() string {
|
|||
|
||||
func (this KillStatement) String() string {
|
||||
return print("KILL %v",
|
||||
this.Name,
|
||||
this.What,
|
||||
)
|
||||
}
|
||||
|
||||
|
|
12
web/rpc.go
12
web/rpc.go
|
@ -34,6 +34,18 @@ func (r *rpc) Query(c *fibre.Context, sql string, vars map[string]interface{}) (
|
|||
return db.Execute(c, sql, vars)
|
||||
}
|
||||
|
||||
func (r *rpc) Kill(c *fibre.Context, query string) (interface{}, error) {
|
||||
return db.Execute(c, "KILL $query", map[string]interface{}{
|
||||
"query": query,
|
||||
})
|
||||
}
|
||||
|
||||
func (r *rpc) Live(c *fibre.Context, class string) (interface{}, error) {
|
||||
return db.Execute(c, "LIVE SELECT * FROM $class", map[string]interface{}{
|
||||
"class": sql.NewTable(class),
|
||||
})
|
||||
}
|
||||
|
||||
func (r *rpc) Select(c *fibre.Context, class string, thing interface{}) (interface{}, error) {
|
||||
switch thing := thing.(type) {
|
||||
case *fibre.RPCNull:
|
||||
|
|
Loading…
Reference in a new issue