Update to work with sql parser improvements

This commit is contained in:
Tobie Morgan Hitchcock 2016-09-06 14:33:02 +01:00
parent fe7ab7019c
commit a0d3f6ec2a
11 changed files with 467 additions and 194 deletions

View file

@ -22,33 +22,41 @@ import (
"github.com/abcum/surreal/util/uuid"
)
func executeCreateStatement(ast *sql.CreateStatement) (out []interface{}, err error) {
func executeCreateStatement(txn kvs.TX, ast *sql.CreateStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, w := range ast.What {
if what, ok := w.(*sql.Thing); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: what.ID}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, key)
if ret, err := create(txn, doc, ast); err != nil {
doc := item.New(kv, txn, key)
if ret, err := create(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
}
}
if what, ok := w.(sql.Table); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what, ID: uuid.NewV5(uuid.NewV4().UUID, ast.KV).String()}
if what, ok := w.(*sql.Table); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: uuid.NewV5(uuid.NewV4().UUID, ast.KV).String()}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, key)
if ret, err := create(txn, doc, ast); err != nil {
doc := item.New(kv, txn, key)
if ret, err := create(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
@ -57,32 +65,34 @@ func executeCreateStatement(ast *sql.CreateStatement) (out []interface{}, err er
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func create(txn kvs.TX, doc *item.Doc, ast *sql.CreateStatement) (out interface{}, err error) {
func create(doc *item.Doc, ast *sql.CreateStatement) (out interface{}, err error) {
if !doc.Allow(txn, "create") {
if err = doc.Merge(ast.Data); err != nil {
return
}
if !doc.Allow("CREATE") {
return nil, nil
}
if err = doc.Merge(txn, ast.Data); err != nil {
return nil, err
if err = doc.StoreIndex(); err != nil {
return
}
if err = doc.StoreIndex(txn); err != nil {
return nil, err
if err = doc.StartThing(); err != nil {
return
}
if err = doc.StartThing(txn); err != nil {
return nil, err
}
if err = doc.StorePatch(txn); err != nil {
return nil, err
if err = doc.StorePatch(); err != nil {
return
}
out = doc.Yield(ast.Echo, sql.AFTER)

View file

@ -63,6 +63,8 @@ func Exit() {
// Prepare prepares a query for parameterization for future execution
func Prepare(sql string, param ...interface{}) string {
// IMPORTANT Need to improve database paramaterization
return fmt.Sprintf(sql, param...)
}
@ -120,7 +122,12 @@ func detail(e error) interface{} {
func execute(ctx *fibre.Context, ast *sql.Query, chn chan<- interface{}) {
var txn kvs.TX
defer func() {
if txn != nil {
txn.Rollback()
}
if r := recover(); r != nil {
if err, ok := r.(error); ok {
fmt.Printf("%s", debug.Stack())
@ -143,37 +150,70 @@ func execute(ctx *fibre.Context, ast *sql.Query, chn chan<- interface{}) {
continue
case *sql.SelectStatement:
res, err = executeSelectStatement(stm)
res, err = executeSelectStatement(txn, stm)
case *sql.CreateStatement:
res, err = executeCreateStatement(stm)
res, err = executeCreateStatement(txn, stm)
case *sql.UpdateStatement:
res, err = executeUpdateStatement(stm)
res, err = executeUpdateStatement(txn, stm)
case *sql.ModifyStatement:
res, err = executeModifyStatement(stm)
res, err = executeModifyStatement(txn, stm)
case *sql.DeleteStatement:
res, err = executeDeleteStatement(stm)
res, err = executeDeleteStatement(txn, stm)
case *sql.RelateStatement:
res, err = executeRelateStatement(stm)
res, err = executeRelateStatement(txn, stm)
case *sql.RecordStatement:
res, err = executeRecordStatement(stm)
res, err = executeRecordStatement(txn, stm)
case *sql.DefineRulesStatement:
res, err = executeDefineRulesStatement(txn, stm)
case *sql.RemoveRulesStatement:
res, err = executeRemoveRulesStatement(txn, stm)
case *sql.DefineTableStatement:
res, err = executeDefineTableStatement(stm)
res, err = executeDefineTableStatement(txn, stm)
case *sql.RemoveTableStatement:
res, err = executeRemoveTableStatement(stm)
res, err = executeRemoveTableStatement(txn, stm)
case *sql.DefineFieldStatement:
res, err = executeDefineFieldStatement(stm)
res, err = executeDefineFieldStatement(txn, stm)
case *sql.RemoveFieldStatement:
res, err = executeRemoveFieldStatement(stm)
res, err = executeRemoveFieldStatement(txn, stm)
case *sql.DefineIndexStatement:
res, err = executeDefineIndexStatement(stm)
res, err = executeDefineIndexStatement(txn, stm)
case *sql.ResyncIndexStatement:
res, err = executeResyncIndexStatement(stm)
res, err = executeResyncIndexStatement(txn, stm)
case *sql.RemoveIndexStatement:
res, err = executeRemoveIndexStatement(stm)
res, err = executeRemoveIndexStatement(txn, stm)
case *sql.BeginStatement:
if txn != nil {
chn <- fibre.NewHTTPError(400, "Transaction already running")
return
} else if txn, err = db.Txn(true); err != nil {
chn <- err
return
}
case *sql.CommitStatement:
if txn != nil {
txn.Commit()
txn = nil
continue
}
case *sql.CancelStatement:
if txn != nil {
txn.Rollback()
txn = nil
continue
}
}
if err != nil && txn != nil {
txn.Rollback()
chn <- err
}
chn <- &Response{

View file

@ -15,19 +15,28 @@
package db
import (
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/keys"
"github.com/abcum/surreal/util/pack"
)
func executeDefineTableStatement(ast *sql.DefineTableStatement) (out []interface{}, err error) {
func executeDefineTableStatement(txn kvs.TX, ast *sql.DefineTableStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -45,34 +54,81 @@ func executeDefineTableStatement(ast *sql.DefineTableStatement) (out []interface
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func executeDefineFieldStatement(ast *sql.DefineFieldStatement) (out []interface{}, err error) {
func executeDefineRulesStatement(txn kvs.TX, ast *sql.DefineRulesStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
doc := data.New()
doc.Set(ast.Name, "name")
doc.Set(ast.Type, "type")
doc.Set(ast.Enum, "enum")
doc.Set(ast.Code, "code")
doc.Set(ast.Min, "min")
doc.Set(ast.Max, "max")
doc.Set(ast.Match, "match")
doc.Set(ast.Default, "default")
doc.Set(ast.Notnull, "notnull")
doc.Set(ast.Readonly, "readonly")
doc.Set(ast.Mandatory, "mandatory")
doc.Set(ast.Validate, "validate")
for _, TB := range ast.What {
for _, RU := range ast.When {
// Set the database definition
dkey := &keys.DB{KV: ast.KV, NS: ast.NS, DB: ast.DB}
if err := txn.Put(dkey.Encode(), nil); err != nil {
return nil, err
}
// Set the table definition
tkey := &keys.TB{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB}
if err := txn.Put(tkey.Encode(), nil); err != nil {
return nil, err
}
// Set the field definition
rkey := &keys.RU{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, RU: RU}
if err := txn.Put(rkey.Encode(), pack.ToPACK(ast)); err != nil {
return nil, err
}
}
}
if local {
txn.Commit()
}
return
}
func executeDefineFieldStatement(txn kvs.TX, ast *sql.DefineFieldStatement) (out []interface{}, err error) {
var local bool
if ast.EX {
return append(out, ast), nil
}
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -90,37 +146,36 @@ func executeDefineFieldStatement(ast *sql.DefineFieldStatement) (out []interface
// Set the field definition
fkey := &keys.FD{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, FD: ast.Name}
if err := txn.Put(fkey.Encode(), doc.ToPACK()); err != nil {
if err := txn.Put(fkey.Encode(), pack.ToPACK(ast)); err != nil {
return nil, err
}
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func executeDefineIndexStatement(ast *sql.DefineIndexStatement) (out []interface{}, err error) {
func executeDefineIndexStatement(txn kvs.TX, ast *sql.DefineIndexStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
doc := data.New()
// doc.Set(ast.Name, "name")
// doc.Set(ast.Type, "type")
// doc.Set(ast.Code, "code")
// doc.Set(ast.Min, "min")
// doc.Set(ast.Max, "max")
// doc.Set(ast.Default, "default")
// doc.Set(ast.Notnull, "notnull")
// doc.Set(ast.Readonly, "readonly")
// doc.Set(ast.Mandatory, "mandatory")
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -138,13 +193,15 @@ func executeDefineIndexStatement(ast *sql.DefineIndexStatement) (out []interface
// Set the index definition
ikey := &keys.IX{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, IX: ast.Name}
if err := txn.Put(ikey.Encode(), doc.ToPACK()); err != nil {
if err := txn.Put(ikey.Encode(), pack.ToPACK(ast)); err != nil {
return nil, err
}
}
txn.Commit()
if local {
txn.Commit()
}
return

View file

@ -21,35 +21,43 @@ import (
"github.com/abcum/surreal/util/keys"
)
func executeDeleteStatement(ast *sql.DeleteStatement) (out []interface{}, err error) {
func executeDeleteStatement(txn kvs.TX, ast *sql.DeleteStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, w := range ast.What {
if what, ok := w.(*sql.Thing); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: what.ID}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, key)
if ret, err := delete(txn, doc, ast); err != nil {
doc := item.New(kv, txn, key)
if ret, err := delete(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
}
}
if what, ok := w.(sql.Table); ok {
beg := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what, ID: keys.Prefix}
end := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what, ID: keys.Suffix}
if what, ok := w.(*sql.Table); ok {
beg := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Prefix}
end := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Suffix}
kvs, _ := txn.RGet(beg.Encode(), end.Encode(), 0)
for _, kv := range kvs {
doc := item.New(kv, nil)
if ret, err := delete(txn, doc, ast); err != nil {
doc := item.New(kv, txn, nil)
if ret, err := delete(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
@ -59,38 +67,40 @@ func executeDeleteStatement(ast *sql.DeleteStatement) (out []interface{}, err er
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func delete(txn kvs.TX, doc *item.Doc, ast *sql.DeleteStatement) (out interface{}, err error) {
func delete(doc *item.Doc, ast *sql.DeleteStatement) (out interface{}, err error) {
if !doc.Allow(txn, "delete") {
return nil, nil
if !doc.Allow("DELETE") {
return
}
if !doc.Check(txn, ast.Cond) {
return nil, nil
if !doc.Check(ast.Cond) {
return
}
if err = doc.Erase(txn, nil); err != nil {
return nil, err
if err = doc.Erase(); err != nil {
return
}
if err = doc.PurgeIndex(txn); err != nil {
return nil, err
if err = doc.PurgeIndex(); err != nil {
return
}
if err = doc.PurgeThing(txn); err != nil {
return nil, err
if err = doc.PurgeThing(); err != nil {
return
}
if ast.Hard {
if err = doc.PurgePatch(txn); err != nil {
return nil, err
if err = doc.PurgePatch(); err != nil {
return
}
}

View file

@ -21,22 +21,30 @@ import (
"github.com/abcum/surreal/util/keys"
)
func executeModifyStatement(ast *sql.ModifyStatement) (out []interface{}, err error) {
func executeModifyStatement(txn kvs.TX, ast *sql.ModifyStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, w := range ast.What {
if what, ok := w.(*sql.Thing); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: what.ID}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, key)
if ret, err := modify(txn, doc, ast); err != nil {
doc := item.New(kv, txn, key)
if ret, err := modify(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
@ -45,36 +53,38 @@ func executeModifyStatement(ast *sql.ModifyStatement) (out []interface{}, err er
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func modify(txn kvs.TX, doc *item.Doc, ast *sql.ModifyStatement) (out interface{}, err error) {
func modify(doc *item.Doc, ast *sql.ModifyStatement) (out interface{}, err error) {
if !doc.Allow(txn, "modify") {
return nil, nil
if !doc.Allow("UPDATE") {
return
}
if !doc.Check(txn, ast.Cond) {
return nil, nil
if !doc.Check(ast.Cond) {
return
}
if err = doc.Merge(txn, ast.Diff); err != nil {
return nil, err
if err = doc.Merge(ast.Diff); err != nil {
return
}
if err = doc.StoreIndex(txn); err != nil {
return nil, err
if err = doc.StoreIndex(); err != nil {
return
}
if err = doc.StoreThing(txn); err != nil {
return nil, err
if err = doc.StoreThing(); err != nil {
return
}
if err = doc.StorePatch(txn); err != nil {
return nil, err
if err = doc.StorePatch(); err != nil {
return
}
out = doc.Yield(ast.Echo, sql.DIFF)

View file

@ -15,9 +15,10 @@
package db
import (
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/sql"
)
func executeRecordStatement(ast *sql.RecordStatement) ([]interface{}, error) {
func executeRecordStatement(txn kvs.TX, ast *sql.RecordStatement) ([]interface{}, error) {
return nil, nil
}

View file

@ -15,9 +15,10 @@
package db
import (
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/sql"
)
func executeRelateStatement(ast *sql.RelateStatement) ([]interface{}, error) {
func executeRelateStatement(txn kvs.TX, ast *sql.RelateStatement) ([]interface{}, error) {
return nil, nil
}

View file

@ -15,18 +15,27 @@
package db
import (
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/keys"
)
func executeRemoveTableStatement(ast *sql.RemoveTableStatement) (out []interface{}, err error) {
func executeRemoveTableStatement(txn kvs.TX, ast *sql.RemoveTableStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -36,6 +45,12 @@ func executeRemoveTableStatement(ast *sql.RemoveTableStatement) (out []interface
return nil, err
}
// Remove the rules config
rkey := &keys.RU{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, RU: keys.Ignore}
if err := txn.PDel(rkey.Encode()); err != nil {
return nil, err
}
// Remove the field config
fkey := &keys.FD{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, FD: keys.Ignore}
if err := txn.PDel(fkey.Encode()); err != nil {
@ -56,20 +71,69 @@ func executeRemoveTableStatement(ast *sql.RemoveTableStatement) (out []interface
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func executeRemoveFieldStatement(ast *sql.RemoveFieldStatement) (out []interface{}, err error) {
func executeRemoveRulesStatement(txn kvs.TX, ast *sql.RemoveRulesStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
for _, RU := range ast.When {
// Remove the rules config
ckey := &keys.RU{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, RU: RU}
if err := txn.Del(ckey.Encode()); err != nil {
return nil, err
}
}
}
if local {
txn.Commit()
}
return
}
func executeRemoveFieldStatement(txn kvs.TX, ast *sql.RemoveFieldStatement) (out []interface{}, err error) {
var local bool
if ast.EX {
return append(out, ast), nil
}
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -81,20 +145,30 @@ func executeRemoveFieldStatement(ast *sql.RemoveFieldStatement) (out []interface
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func executeRemoveIndexStatement(ast *sql.RemoveIndexStatement) (out []interface{}, err error) {
func executeRemoveIndexStatement(txn kvs.TX, ast *sql.RemoveIndexStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -112,7 +186,9 @@ func executeRemoveIndexStatement(ast *sql.RemoveIndexStatement) (out []interface
}
txn.Commit()
if local {
txn.Commit()
}
return

View file

@ -21,14 +21,21 @@ import (
"github.com/abcum/surreal/util/keys"
)
func executeResyncIndexStatement(ast *sql.ResyncIndexStatement) (out []interface{}, err error) {
func executeResyncIndexStatement(txn kvs.TX, ast *sql.ResyncIndexStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, TB := range ast.What {
@ -44,23 +51,25 @@ func executeResyncIndexStatement(ast *sql.ResyncIndexStatement) (out []interface
iend := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: TB, ID: keys.Suffix}
kvs, _ := txn.RGet(ibeg.Encode(), iend.Encode(), 0)
for _, kv := range kvs {
doc := item.New(kv, nil)
if err := resync(txn, doc, ast); err != nil {
doc := item.New(kv, txn, nil)
if err := resync(doc, ast); err != nil {
return nil, err
}
}
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func resync(txn kvs.TX, doc *item.Doc, ast *sql.ResyncIndexStatement) (err error) {
func resync(doc *item.Doc, ast *sql.ResyncIndexStatement) (err error) {
if err = doc.StoreIndex(txn); err != nil {
if err = doc.StoreIndex(); err != nil {
return err
}

View file

@ -15,22 +15,71 @@
package db
import (
"github.com/abcum/surreal/kvs"
"github.com/abcum/surreal/sql"
"github.com/abcum/surreal/util/data"
"github.com/abcum/surreal/util/item"
"github.com/abcum/surreal/util/keys"
)
func executeSelectStatement(ast *sql.SelectStatement) (out []interface{}, err error) {
func executeSelectStatement(txn kvs.TX, ast *sql.SelectStatement) (out []interface{}, err error) {
kvs, err := db.All()
if ast.EX {
return append(out, ast), nil
}
for _, kv := range kvs {
if txn == nil {
txn, err = db.Txn(false)
if err != nil {
return
}
defer txn.Close()
}
for _, w := range ast.What {
if what, ok := w.(*sql.Thing); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: what.ID}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, txn, key)
if ret, err := detect(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
}
}
if what, ok := w.(*sql.Table); ok {
beg := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Prefix}
end := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Suffix}
kvs, _ := txn.RGet(beg.Encode(), end.Encode(), 0)
for _, kv := range kvs {
doc := item.New(kv, txn, nil)
if ret, err := detect(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
}
}
}
out = append(out, map[string]interface{}{
"key": string(kv.Key()),
"val": data.NewFromPACK(kv.Val()).Data(),
})
}
return
}
func detect(doc *item.Doc, ast *sql.SelectStatement) (out interface{}, err error) {
if !doc.Allow("SELECT") {
return nil, nil
}
if !doc.Check(ast.Cond) {
return
}
out = doc.Blaze(ast)
return
}

View file

@ -21,35 +21,43 @@ import (
"github.com/abcum/surreal/util/keys"
)
func executeUpdateStatement(ast *sql.UpdateStatement) (out []interface{}, err error) {
func executeUpdateStatement(txn kvs.TX, ast *sql.UpdateStatement) (out []interface{}, err error) {
txn, err := db.Txn(true)
if err != nil {
return
var local bool
if ast.EX {
return append(out, ast), nil
}
defer txn.Rollback()
if txn == nil {
local = true
txn, err = db.Txn(true)
if err != nil {
return
}
defer txn.Rollback()
}
for _, w := range ast.What {
if what, ok := w.(*sql.Thing); ok {
key := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: what.ID}
kv, _ := txn.Get(key.Encode())
doc := item.New(kv, key)
if ret, err := update(txn, doc, ast); err != nil {
doc := item.New(kv, txn, key)
if ret, err := update(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
}
}
if what, ok := w.(sql.Table); ok {
beg := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what, ID: keys.Prefix}
end := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what, ID: keys.Suffix}
if what, ok := w.(*sql.Table); ok {
beg := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Prefix}
end := &keys.Thing{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: what.TB, ID: keys.Suffix}
kvs, _ := txn.RGet(beg.Encode(), end.Encode(), 0)
for _, kv := range kvs {
doc := item.New(kv, nil)
if ret, err := update(txn, doc, ast); err != nil {
doc := item.New(kv, txn, nil)
if ret, err := update(doc, ast); err != nil {
return nil, err
} else if ret != nil {
out = append(out, ret)
@ -59,36 +67,38 @@ func executeUpdateStatement(ast *sql.UpdateStatement) (out []interface{}, err er
}
txn.Commit()
if local {
txn.Commit()
}
return
}
func update(txn kvs.TX, doc *item.Doc, ast *sql.UpdateStatement) (out interface{}, err error) {
func update(doc *item.Doc, ast *sql.UpdateStatement) (out interface{}, err error) {
if !doc.Allow(txn, "update") {
return nil, nil
if !doc.Allow("UPDATE") {
return
}
if !doc.Check(txn, ast.Cond) {
return nil, nil
if !doc.Check(ast.Cond) {
return
}
if err = doc.Merge(txn, ast.Data); err != nil {
return nil, err
if err = doc.Merge(ast.Data); err != nil {
return
}
if err = doc.StoreIndex(txn); err != nil {
return nil, err
if err = doc.StoreIndex(); err != nil {
return
}
if err = doc.StoreThing(txn); err != nil {
return nil, err
if err = doc.StoreThing(); err != nil {
return
}
if err = doc.StorePatch(txn); err != nil {
return nil, err
if err = doc.StorePatch(); err != nil {
return
}
out = doc.Yield(ast.Echo, sql.AFTER)