Enable parameters in LIVE queries

This commit is contained in:
Tobie Morgan Hitchcock 2017-12-08 10:05:21 +00:00
parent 92ecba9154
commit e3c7aacd66
8 changed files with 1225 additions and 1138 deletions

View file

@ -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

View file

@ -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,8 +227,23 @@ 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}
txn.Clr(key.Encode())
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,18 +318,52 @@ 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
}
// Delete the live query from the saved queries.
for _, w := range stm.What {
delete(s.lives, qry.ID)
switch what := w.(type) {
// Delete the live query from the database layer.
default:
return nil, fmt.Errorf("Can not execute KILL query using value '%v'", what)
key := &keys.LV{KV: qry.KV, NS: qry.NS, DB: qry.DB, TB: qry.What.TB, LV: qry.ID}
_, err = e.dbo.Clr(key.Encode())
case string:
if qry, ok := s.lives[what]; ok {
// Delete the live query from the saved queries.
delete(s.lives, qry.ID)
// Delete the live query from the database layer.
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())
}
}
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -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.

View file

@ -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
}

View file

@ -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"}},
}}},
},
{

View file

@ -203,7 +203,7 @@ func (this LiveStatement) String() string {
func (this KillStatement) String() string {
return print("KILL %v",
this.Name,
this.What,
)
}

View file

@ -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: