Add SQL RUN query statement type
This commit is contained in:
parent
ea1749f03f
commit
ac19b552e5
7 changed files with 250 additions and 26 deletions
39
db/run.go
Normal file
39
db/run.go
Normal file
|
@ -0,0 +1,39 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/abcum/surreal/sql"
|
||||
)
|
||||
|
||||
func (e *executor) executeRun(ctx context.Context, stm *sql.RunStatement) (out []interface{}, err error) {
|
||||
|
||||
val, err := e.fetch(ctx, stm, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
switch val := val.(type) {
|
||||
case []interface{}:
|
||||
out = val
|
||||
case interface{}:
|
||||
out = append(out, val)
|
||||
}
|
||||
|
||||
return
|
||||
|
||||
}
|
106
db/run_test.go
Normal file
106
db/run_test.go
Normal file
|
@ -0,0 +1,106 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package db
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
type Handler struct {
|
||||
sync.Mutex
|
||||
count int
|
||||
}
|
||||
|
||||
func (s *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
s.count++
|
||||
fmt.Fprintf(w, "SERVER OK: %d", s.count)
|
||||
}
|
||||
|
||||
func TestRun(t *testing.T) {
|
||||
|
||||
handler := &Handler{}
|
||||
server := httptest.NewServer(handler)
|
||||
defer server.Close()
|
||||
|
||||
Convey("Run statement which runs http requests", t, func() {
|
||||
|
||||
setupDB()
|
||||
|
||||
func() {
|
||||
|
||||
txt := `
|
||||
USE NS test DB test;
|
||||
DEFINE TABLE test PERMISSIONS FULL;
|
||||
DEFINE TABLE temp PERMISSIONS FOR SELECT FULL;
|
||||
DEFINE EVENT done ON test WHEN true THEN (
|
||||
CREATE temp:main;
|
||||
RUN http.get("` + server.URL + `");
|
||||
RUN http.put("` + server.URL + `");
|
||||
RUN http.post("` + server.URL + `");
|
||||
RUN http.delete("` + server.URL + `");
|
||||
RUN http.async.get("` + server.URL + `");
|
||||
RUN http.async.put("` + server.URL + `");
|
||||
RUN http.async.post("` + server.URL + `");
|
||||
RUN http.async.delete("` + server.URL + `");
|
||||
);
|
||||
`
|
||||
|
||||
res, err := Execute(setupKV(), txt, nil)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldHaveLength, 4)
|
||||
So(res[1].Status, ShouldEqual, "OK")
|
||||
So(res[2].Status, ShouldEqual, "OK")
|
||||
|
||||
}()
|
||||
|
||||
func() {
|
||||
|
||||
txt := `
|
||||
USE NS test DB test;
|
||||
SELECT * FROM test, temp;
|
||||
CREATE test:main;
|
||||
SELECT * FROM test, temp;
|
||||
`
|
||||
|
||||
res, err := Execute(setupSC(), txt, nil)
|
||||
time.Sleep(1 * time.Second)
|
||||
So(err, ShouldBeNil)
|
||||
So(res, ShouldHaveLength, 4)
|
||||
So(res[1].Status, ShouldEqual, "OK")
|
||||
So(res[1].Result, ShouldHaveLength, 0)
|
||||
So(res[2].Status, ShouldEqual, "OK")
|
||||
So(res[2].Result, ShouldHaveLength, 1)
|
||||
So(res[3].Status, ShouldEqual, "OK")
|
||||
So(res[3].Result, ShouldHaveLength, 2)
|
||||
|
||||
handler.Lock()
|
||||
So(handler.count, ShouldEqual, 8)
|
||||
handler.Unlock()
|
||||
|
||||
}()
|
||||
|
||||
})
|
||||
|
||||
}
|
10
sql/ast.go
10
sql/ast.go
|
@ -101,6 +101,16 @@ type IfStatement struct {
|
|||
Else Expr `cork:"else" codec:"else"`
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// Run
|
||||
// --------------------------------------------------
|
||||
|
||||
// RunStatement represents a run clause.
|
||||
type RunStatement struct {
|
||||
RW bool `cork:"-" codec:"-"`
|
||||
Expr Expr `cork:"expr" codec:"expr"`
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// LET
|
||||
// --------------------------------------------------
|
||||
|
|
82
sql/cork.go
82
sql/cork.go
|
@ -930,6 +930,36 @@ func (this *IfStatement) UnmarshalCORK(r *cork.Reader) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// RunStatement
|
||||
// --------------------------------------------------
|
||||
|
||||
func init() {
|
||||
cork.Register(&RunStatement{})
|
||||
}
|
||||
|
||||
func (this *RunStatement) Decode(src []byte) {
|
||||
pack.Decode(src, this)
|
||||
}
|
||||
|
||||
func (this *RunStatement) Encode() (dst []byte) {
|
||||
return pack.Encode(this)
|
||||
}
|
||||
|
||||
func (this *RunStatement) ExtendCORK() byte {
|
||||
return 0x72
|
||||
}
|
||||
|
||||
func (this *RunStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
w.EncodeAny(this.Expr)
|
||||
return
|
||||
}
|
||||
|
||||
func (this *RunStatement) UnmarshalCORK(r *cork.Reader) (err error) {
|
||||
r.DecodeAny(&this.Expr)
|
||||
return
|
||||
}
|
||||
|
||||
// --------------------------------------------------
|
||||
// LiveStatement
|
||||
// --------------------------------------------------
|
||||
|
@ -947,7 +977,7 @@ func (this *LiveStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *LiveStatement) ExtendCORK() byte {
|
||||
return 0x72
|
||||
return 0x73
|
||||
}
|
||||
|
||||
func (this *LiveStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -987,7 +1017,7 @@ func (this *SelectStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *SelectStatement) ExtendCORK() byte {
|
||||
return 0x73
|
||||
return 0x74
|
||||
}
|
||||
|
||||
func (this *SelectStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1041,7 +1071,7 @@ func (this *CreateStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *CreateStatement) ExtendCORK() byte {
|
||||
return 0x74
|
||||
return 0x75
|
||||
}
|
||||
|
||||
func (this *CreateStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1083,7 +1113,7 @@ func (this *UpdateStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *UpdateStatement) ExtendCORK() byte {
|
||||
return 0x75
|
||||
return 0x76
|
||||
}
|
||||
|
||||
func (this *UpdateStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1127,7 +1157,7 @@ func (this *DeleteStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DeleteStatement) ExtendCORK() byte {
|
||||
return 0x76
|
||||
return 0x77
|
||||
}
|
||||
|
||||
func (this *DeleteStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1171,7 +1201,7 @@ func (this *RelateStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RelateStatement) ExtendCORK() byte {
|
||||
return 0x77
|
||||
return 0x78
|
||||
}
|
||||
|
||||
func (this *RelateStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1219,7 +1249,7 @@ func (this *InsertStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *InsertStatement) ExtendCORK() byte {
|
||||
return 0x78
|
||||
return 0x79
|
||||
}
|
||||
|
||||
func (this *InsertStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1261,7 +1291,7 @@ func (this *UpsertStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *UpsertStatement) ExtendCORK() byte {
|
||||
return 0x79
|
||||
return 0x80
|
||||
}
|
||||
|
||||
func (this *UpsertStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1303,7 +1333,7 @@ func (this *DefineNamespaceStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineNamespaceStatement) ExtendCORK() byte {
|
||||
return 0x80
|
||||
return 0x81
|
||||
}
|
||||
|
||||
func (this *DefineNamespaceStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1333,7 +1363,7 @@ func (this *RemoveNamespaceStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveNamespaceStatement) ExtendCORK() byte {
|
||||
return 0x81
|
||||
return 0x82
|
||||
}
|
||||
|
||||
func (this *RemoveNamespaceStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1363,7 +1393,7 @@ func (this *DefineDatabaseStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineDatabaseStatement) ExtendCORK() byte {
|
||||
return 0x82
|
||||
return 0x83
|
||||
}
|
||||
|
||||
func (this *DefineDatabaseStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1393,7 +1423,7 @@ func (this *RemoveDatabaseStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveDatabaseStatement) ExtendCORK() byte {
|
||||
return 0x83
|
||||
return 0x84
|
||||
}
|
||||
|
||||
func (this *RemoveDatabaseStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1423,7 +1453,7 @@ func (this *DefineLoginStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineLoginStatement) ExtendCORK() byte {
|
||||
return 0x84
|
||||
return 0x85
|
||||
}
|
||||
|
||||
func (this *DefineLoginStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1459,7 +1489,7 @@ func (this *RemoveLoginStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveLoginStatement) ExtendCORK() byte {
|
||||
return 0x85
|
||||
return 0x86
|
||||
}
|
||||
|
||||
func (this *RemoveLoginStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1491,7 +1521,7 @@ func (this *DefineTokenStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineTokenStatement) ExtendCORK() byte {
|
||||
return 0x86
|
||||
return 0x87
|
||||
}
|
||||
|
||||
func (this *DefineTokenStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1527,7 +1557,7 @@ func (this *RemoveTokenStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveTokenStatement) ExtendCORK() byte {
|
||||
return 0x87
|
||||
return 0x88
|
||||
}
|
||||
|
||||
func (this *RemoveTokenStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1559,7 +1589,7 @@ func (this *DefineScopeStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineScopeStatement) ExtendCORK() byte {
|
||||
return 0x88
|
||||
return 0x89
|
||||
}
|
||||
|
||||
func (this *DefineScopeStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1603,7 +1633,7 @@ func (this *RemoveScopeStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveScopeStatement) ExtendCORK() byte {
|
||||
return 0x89
|
||||
return 0x90
|
||||
}
|
||||
|
||||
func (this *RemoveScopeStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1633,7 +1663,7 @@ func (this *DefineTableStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineTableStatement) ExtendCORK() byte {
|
||||
return 0x90
|
||||
return 0x91
|
||||
}
|
||||
|
||||
func (this *DefineTableStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1679,7 +1709,7 @@ func (this *RemoveTableStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveTableStatement) ExtendCORK() byte {
|
||||
return 0x91
|
||||
return 0x92
|
||||
}
|
||||
|
||||
func (this *RemoveTableStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1709,7 +1739,7 @@ func (this *DefineEventStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineEventStatement) ExtendCORK() byte {
|
||||
return 0x92
|
||||
return 0x93
|
||||
}
|
||||
|
||||
func (this *DefineEventStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1745,7 +1775,7 @@ func (this *RemoveEventStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveEventStatement) ExtendCORK() byte {
|
||||
return 0x93
|
||||
return 0x94
|
||||
}
|
||||
|
||||
func (this *RemoveEventStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1777,7 +1807,7 @@ func (this *DefineFieldStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineFieldStatement) ExtendCORK() byte {
|
||||
return 0x94
|
||||
return 0x95
|
||||
}
|
||||
|
||||
func (this *DefineFieldStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1821,7 +1851,7 @@ func (this *RemoveFieldStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveFieldStatement) ExtendCORK() byte {
|
||||
return 0x95
|
||||
return 0x96
|
||||
}
|
||||
|
||||
func (this *RemoveFieldStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1853,7 +1883,7 @@ func (this *DefineIndexStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *DefineIndexStatement) ExtendCORK() byte {
|
||||
return 0x96
|
||||
return 0x97
|
||||
}
|
||||
|
||||
func (this *DefineIndexStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
@ -1889,7 +1919,7 @@ func (this *RemoveIndexStatement) Encode() (dst []byte) {
|
|||
}
|
||||
|
||||
func (this *RemoveIndexStatement) ExtendCORK() byte {
|
||||
return 0x97
|
||||
return 0x98
|
||||
}
|
||||
|
||||
func (this *RemoveIndexStatement) MarshalCORK(w *cork.Writer) (err error) {
|
||||
|
|
31
sql/run.go
Normal file
31
sql/run.go
Normal file
|
@ -0,0 +1,31 @@
|
|||
// Copyright © 2016 Abcum Ltd
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package sql
|
||||
|
||||
func (p *parser) parseRunStatement() (stmt *RunStatement, err error) {
|
||||
|
||||
stmt = &RunStatement{}
|
||||
|
||||
stmt.Expr, err = p.parseExpr()
|
||||
|
||||
// If this query has any subqueries which
|
||||
// need to alter the database then mark
|
||||
// this query as a writeable statement.
|
||||
|
||||
stmt.RW = p.buf.rw
|
||||
|
||||
return
|
||||
|
||||
}
|
|
@ -168,6 +168,12 @@ func (this InfoStatement) String() string {
|
|||
}
|
||||
}
|
||||
|
||||
func (this RunStatement) String() string {
|
||||
return print("RUN %v",
|
||||
this.Expr,
|
||||
)
|
||||
}
|
||||
|
||||
func (this IfStatement) String() string {
|
||||
m := make([]string, len(this.Cond))
|
||||
for k := range this.Cond {
|
||||
|
|
|
@ -169,6 +169,7 @@ const (
|
|||
RELATE
|
||||
REMOVE
|
||||
RETURN
|
||||
RUN
|
||||
SCHEMAFULL
|
||||
SCHEMALESS
|
||||
SCOPE
|
||||
|
@ -339,6 +340,7 @@ var tokens = [...]string{
|
|||
RELATE: "RELATE",
|
||||
REMOVE: "REMOVE",
|
||||
RETURN: "RETURN",
|
||||
RUN: "RUN",
|
||||
SCHEMAFULL: "SCHEMAFULL",
|
||||
SCHEMALESS: "SCHEMALESS",
|
||||
SCOPE: "SCOPE",
|
||||
|
|
Loading…
Reference in a new issue