Add SQL VIEWs

This commit is contained in:
Tobie Morgan Hitchcock 2016-09-21 00:36:37 +01:00
parent f37ec653d1
commit 66f09db9f5
7 changed files with 185 additions and 4 deletions

View file

@ -42,13 +42,24 @@ func executeInfoStatement(txn kvs.TX, ast *sql.InfoStatement) (out []interface{}
// Get the table definitions // Get the table definitions
tbeg := &keys.TB{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: keys.Prefix} tbeg := &keys.TB{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: keys.Prefix}
tend := &keys.TB{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: keys.Suffix} tend := &keys.TB{KV: ast.KV, NS: ast.NS, DB: ast.DB, TB: keys.Suffix}
kvs, _ := txn.RGet(tbeg.Encode(), tend.Encode(), 0) tkvs, _ := txn.RGet(tbeg.Encode(), tend.Encode(), 0)
for _, kv := range kvs { for _, kv := range tkvs {
key := &keys.TB{} key := &keys.TB{}
key.Decode(kv.Key()) key.Decode(kv.Key())
res.Inc(key.TB, "tables") res.Inc(key.TB, "tables")
} }
// Get the table definitions
vbeg := &keys.VW{KV: ast.KV, NS: ast.NS, DB: ast.DB, VW: keys.Prefix}
vend := &keys.VW{KV: ast.KV, NS: ast.NS, DB: ast.DB, VW: keys.Suffix}
vkvs, _ := txn.RGet(vbeg.Encode(), vend.Encode(), 0)
for _, kv := range vkvs {
key, val := &keys.VW{}, &sql.DefineViewStatement{}
key.Decode(kv.Key())
pack.Decode(kv.Val(), val)
res.Inc(val, "views")
}
out = append(out, res.Data()) out = append(out, res.Data())
} else { } else {

View file

@ -257,6 +257,30 @@ type RemoveIndexStatement struct {
What []string `codec:"-"` What []string `codec:"-"`
} }
// --------------------------------------------------
// View
// --------------------------------------------------
// DefineViewStatement represents an SQL DEFINE VIEW statement.
type DefineViewStatement struct {
KV string `codec:"-"`
NS string `codec:"-"`
DB string `codec:"-"`
Name string `codec:"name"`
Expr []*Field `codec:"expr"`
What []Expr `codec:"what"`
Cond []Expr `codec:"cond"`
Group []*Group `codec:"group"`
}
// RemoveViewStatement represents an SQL REMOVE VIEW statement.
type RemoveViewStatement struct {
KV string `codec:"-"`
NS string `codec:"-"`
DB string `codec:"-"`
Name string `codec:"-"`
}
// -------------------------------------------------- // --------------------------------------------------
// Literals // Literals
// -------------------------------------------------- // --------------------------------------------------

View file

@ -17,7 +17,7 @@ package sql
func (p *parser) parseDefineStatement() (Statement, error) { func (p *parser) parseDefineStatement() (Statement, error) {
// Inspect the next token. // Inspect the next token.
tok, _, err := p.shouldBe(TABLE, RULES, FIELD, INDEX) tok, _, err := p.shouldBe(TABLE, RULES, FIELD, INDEX, VIEW)
switch tok { switch tok {
case TABLE: case TABLE:
@ -28,6 +28,8 @@ func (p *parser) parseDefineStatement() (Statement, error) {
return p.parseDefineFieldStatement() return p.parseDefineFieldStatement()
case INDEX: case INDEX:
return p.parseDefineIndexStatement() return p.parseDefineIndexStatement()
case VIEW:
return p.parseDefineViewStatement()
default: default:
return nil, err return nil, err
} }

View file

@ -17,7 +17,7 @@ package sql
func (p *parser) parseRemoveStatement() (Statement, error) { func (p *parser) parseRemoveStatement() (Statement, error) {
// Inspect the next token. // Inspect the next token.
tok, _, err := p.shouldBe(TABLE, RULES, FIELD, INDEX) tok, _, err := p.shouldBe(TABLE, RULES, FIELD, INDEX, VIEW)
switch tok { switch tok {
case TABLE: case TABLE:
@ -28,6 +28,8 @@ func (p *parser) parseRemoveStatement() (Statement, error) {
return p.parseRemoveFieldStatement() return p.parseRemoveFieldStatement()
case INDEX: case INDEX:
return p.parseRemoveIndexStatement() return p.parseRemoveIndexStatement()
case VIEW:
return p.parseRemoveViewStatement()
default: default:
return nil, err return nil, err
} }

View file

@ -182,6 +182,7 @@ const (
USE USE
VALIDATE VALIDATE
VERSION VERSION
VIEW
VOID VOID
WHERE WHERE
@ -340,6 +341,7 @@ var tokens = [...]string{
USE: "USE", USE: "USE",
VALIDATE: "VALIDATE", VALIDATE: "VALIDATE",
VERSION: "VERSION", VERSION: "VERSION",
VIEW: "VIEW",
VOID: "VOID", VOID: "VOID",
WHERE: "WHERE", WHERE: "WHERE",
} }

86
sql/view.go Normal file
View file

@ -0,0 +1,86 @@
// 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) parseDefineViewStatement() (stmt *DefineViewStatement, err error) {
stmt = &DefineViewStatement{}
stmt.KV = p.c.Get("KV").(string)
stmt.NS = p.c.Get("NS").(string)
stmt.DB = p.c.Get("DB").(string)
if stmt.Name, err = p.parseName(); err != nil {
return nil, err
}
_, _, err = p.shouldBe(AS)
if err != nil {
return nil, err
}
_, _, err = p.shouldBe(SELECT)
if err != nil {
return nil, err
}
if stmt.Expr, err = p.parseExpr(); err != nil {
return nil, err
}
_, _, err = p.shouldBe(FROM)
if err != nil {
return nil, err
}
if stmt.What, err = p.parseWhat(); err != nil {
return nil, err
}
if stmt.Cond, err = p.parseCond(); err != nil {
return nil, err
}
if stmt.Group, err = p.parseGroup(); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {
return nil, err
}
return
}
func (p *parser) parseRemoveViewStatement() (stmt *RemoveViewStatement, err error) {
stmt = &RemoveViewStatement{}
stmt.KV = p.c.Get("KV").(string)
stmt.NS = p.c.Get("NS").(string)
stmt.DB = p.c.Get("DB").(string)
if stmt.Name, err = p.parseName(); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {
return nil, err
}
return
}

54
util/keys/vw.go Normal file
View file

@ -0,0 +1,54 @@
// 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 keys
import (
"fmt"
)
// VW ...
type VW struct {
KV interface{}
CF interface{}
TK interface{}
NS interface{}
DB interface{}
VW interface{}
}
// init initialises the key
func (k *VW) init() *VW {
k.CF = "!"
k.TK = "v"
return k
}
// Encode encodes the key into binary
func (k *VW) Encode() []byte {
k.init()
return encode(k.KV, k.CF, k.TK, k.NS, k.DB, k.VW)
}
// Decode decodes the key from binary
func (k *VW) Decode(data []byte) {
k.init()
decode(data, &k.KV, &k.CF, &k.TK, &k.NS, &k.DB, &k.VW)
}
// String returns a string representation of the key
func (k *VW) String() string {
k.init()
return fmt.Sprintf("/%s/%s/%s/%s/%s/%s", k.KV, k.CF, k.TK, k.NS, k.DB, k.VW)
}