Add PERMISSIONS and remove DEFINE / REMOVE RULES

This commit is contained in:
Tobie Morgan Hitchcock 2016-11-26 13:39:03 +00:00
parent 2b47e6e0a9
commit fbe34c6083
10 changed files with 184 additions and 321 deletions

View file

@ -282,11 +282,12 @@ type RemoveScopeStatement struct {
// DefineTableStatement represents an SQL DEFINE TABLE statement.
type DefineTableStatement struct {
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
What []string `cork:"-" codec:"-"`
Full bool `cork:"full" codec:"full"`
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
What []string `cork:"-" codec:"-"`
Full bool `cork:"full" codec:"full"`
Perm *PermExpression `cork:"perm" codec:"perm"`
}
// RemoveTableStatement represents an SQL REMOVE TABLE statement.
@ -297,52 +298,29 @@ type RemoveTableStatement struct {
What []string `cork:"-" codec:"-"`
}
// --------------------------------------------------
// Rules
// --------------------------------------------------
// DefineRulesStatement represents an SQL DEFINE RULES statement.
type DefineRulesStatement struct {
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
What []string `cork:"-" codec:"-"`
When []string `cork:"-" codec:"-"`
Rule string `cork:"rule" codec:"rule"`
Cond Expr `cork:"cond" codec:"cond"`
}
// RemoveRulesStatement represents an SQL REMOVE RULES statement.
type RemoveRulesStatement struct {
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
What []string `cork:"-" codec:"-"`
When []string `cork:"-" codec:"-"`
}
// --------------------------------------------------
// Field
// --------------------------------------------------
// DefineFieldStatement represents an SQL DEFINE FIELD statement.
type DefineFieldStatement struct {
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
Name string `cork:"name" codec:"name"`
What []string `cork:"-" codec:"-"`
Type string `cork:"type" codec:"type"`
Enum []interface{} `cork:"enum" codec:"enum"`
Code string `cork:"code" codec:"code"`
Min float64 `cork:"min" codec:"min"`
Max float64 `cork:"max" codec:"max"`
Match string `cork:"match" codec:"match"`
Default interface{} `cork:"default" codec:"default"`
Notnull bool `cork:"notnull" codec:"notnull"`
Readonly bool `cork:"readonly" codec:"readonly"`
Mandatory bool `cork:"mandatory" codec:"mandatory"`
Validate bool `cork:"validate" codec:"validate"`
KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"`
Name string `cork:"name" codec:"name"`
What []string `cork:"-" codec:"-"`
Type string `cork:"type" codec:"type"`
Perm *PermExpression `cork:"perm" codec:"perm"`
Enum []interface{} `cork:"enum" codec:"enum"`
Code string `cork:"code" codec:"code"`
Min float64 `cork:"min" codec:"min"`
Max float64 `cork:"max" codec:"max"`
Match string `cork:"match" codec:"match"`
Default interface{} `cork:"default" codec:"default"`
Notnull bool `cork:"notnull" codec:"notnull"`
Readonly bool `cork:"readonly" codec:"readonly"`
Mandatory bool `cork:"mandatory" codec:"mandatory"`
Validate bool `cork:"validate" codec:"validate"`
}
// RemoveFieldStatement represents an SQL REMOVE FIELD statement.
@ -498,6 +476,15 @@ type SubpExpression struct {
Cond Expr
}
// PermExpression represents a permissions expression.
type PermExpression struct {
Select Expr
Create Expr
Update Expr
Relate Expr
Delete Expr
}
// DiffExpression represents a JSON to DIFF
type DiffExpression struct {
JSON interface{}

View file

@ -1298,66 +1298,6 @@ func (this *RemoveTableStatement) UnmarshalCORK(src []byte) (err error) {
return
}
// --------------------------------------------------
// DefineRulesStatement
// --------------------------------------------------
func init() {
cork.Register(&DefineRulesStatement{})
}
func (this *DefineRulesStatement) ExtendCORK() byte {
return 0x85
}
func (this *DefineRulesStatement) MarshalCORK() (dst []byte, err error) {
b := bytes.NewBuffer(dst)
e := cork.NewEncoder(b)
e.Encode(this.What)
e.Encode(this.When)
e.Encode(this.Rule)
e.Encode(this.Cond)
return b.Bytes(), nil
}
func (this *DefineRulesStatement) UnmarshalCORK(src []byte) (err error) {
b := bytes.NewBuffer(src)
d := cork.NewDecoder(b)
d.Decode(&this.What)
d.Decode(&this.When)
d.Decode(&this.Rule)
d.Decode(&this.Cond)
return
}
// --------------------------------------------------
// RemoveTableStatement
// --------------------------------------------------
func init() {
cork.Register(&RemoveRulesStatement{})
}
func (this *RemoveRulesStatement) ExtendCORK() byte {
return 0x86
}
func (this *RemoveRulesStatement) MarshalCORK() (dst []byte, err error) {
b := bytes.NewBuffer(dst)
e := cork.NewEncoder(b)
e.Encode(this.What)
e.Encode(this.When)
return b.Bytes(), nil
}
func (this *RemoveRulesStatement) UnmarshalCORK(src []byte) (err error) {
b := bytes.NewBuffer(src)
d := cork.NewDecoder(b)
d.Decode(&this.What)
d.Decode(&this.When)
return
}
// --------------------------------------------------
// DefineFieldStatement
// --------------------------------------------------
@ -1367,7 +1307,7 @@ func init() {
}
func (this *DefineFieldStatement) ExtendCORK() byte {
return 0x87
return 0x85
}
func (this *DefineFieldStatement) MarshalCORK() (dst []byte, err error) {
@ -1417,7 +1357,7 @@ func init() {
}
func (this *RemoveFieldStatement) ExtendCORK() byte {
return 0x88
return 0x86
}
func (this *RemoveFieldStatement) MarshalCORK() (dst []byte, err error) {
@ -1445,7 +1385,7 @@ func init() {
}
func (this *DefineIndexStatement) ExtendCORK() byte {
return 0x89
return 0x87
}
func (this *DefineIndexStatement) MarshalCORK() (dst []byte, err error) {
@ -1477,7 +1417,7 @@ func init() {
}
func (this *RemoveIndexStatement) ExtendCORK() byte {
return 0x90
return 0x88
}
func (this *RemoveIndexStatement) MarshalCORK() (dst []byte, err error) {
@ -1505,7 +1445,7 @@ func init() {
}
func (this *DefineViewStatement) ExtendCORK() byte {
return 0x91
return 0x89
}
func (this *DefineViewStatement) MarshalCORK() (dst []byte, err error) {
@ -1539,7 +1479,7 @@ func init() {
}
func (this *RemoveViewStatement) ExtendCORK() byte {
return 0x92
return 0x90
}
func (this *RemoveViewStatement) MarshalCORK() (dst []byte, err error) {

View file

@ -21,7 +21,7 @@ func (p *parser) parseDefineStatement() (Statement, error) {
}
// Inspect the next token.
tok, _, err := p.shouldBe(NAMESPACE, DATABASE, LOGIN, TOKEN, SCOPE, TABLE, RULES, FIELD, INDEX, VIEW)
tok, _, err := p.shouldBe(NAMESPACE, DATABASE, LOGIN, TOKEN, SCOPE, TABLE, FIELD, INDEX, VIEW)
switch tok {
case NAMESPACE:
@ -36,8 +36,6 @@ func (p *parser) parseDefineStatement() (Statement, error) {
return p.parseDefineScopeStatement()
case TABLE:
return p.parseDefineTableStatement()
case RULES:
return p.parseDefineRulesStatement()
case FIELD:
return p.parseDefineFieldStatement()
case INDEX:

View file

@ -36,7 +36,7 @@ func (p *parser) parseDefineFieldStatement() (stmt *DefineFieldStatement, err er
for {
tok, _, exi := p.mightBe(MIN, MAX, TYPE, ENUM, CODE, MATCH, DEFAULT, NOTNULL, READONLY, MANDATORY, VALIDATE)
tok, _, exi := p.mightBe(MIN, MAX, TYPE, ENUM, CODE, MATCH, DEFAULT, NOTNULL, READONLY, MANDATORY, VALIDATE, PERMISSIONS)
if !exi {
break
}
@ -119,6 +119,12 @@ func (p *parser) parseDefineFieldStatement() (stmt *DefineFieldStatement, err er
}
}
if p.is(tok, PERMISSIONS) {
if stmt.Perm, err = p.parsePerms(); err != nil {
return nil, err
}
}
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {

110
sql/perms.go Normal file
View file

@ -0,0 +1,110 @@
// 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) parsePerms() (exp *PermExpression, err error) {
exp = &PermExpression{}
tok, _, err := p.shouldBe(FOR, NONE, FULL, WHERE)
if err != nil {
return exp, err
}
if p.is(tok, NONE, FULL, WHERE) {
var expr Expr
switch tok {
case FULL:
expr = true
case NONE:
expr = false
case WHERE:
if expr, err = p.parseExpr(); err != nil {
return exp, err
}
}
exp.Select = expr
exp.Create = expr
exp.Update = expr
exp.Delete = expr
exp.Relate = expr
return
}
if p.is(tok, FOR) {
for {
var expr Expr
var when []Token
for {
tok, _, err := p.shouldBe(SELECT, CREATE, UPDATE, DELETE, RELATE)
if err != nil {
return exp, err
}
when = append(when, tok)
if _, _, exi := p.mightBe(COMMA); !exi {
break
}
}
tok, _, err := p.shouldBe(FULL, NONE, WHERE)
if err != nil {
return exp, err
}
switch tok {
case FULL:
expr = true
case NONE:
expr = false
case WHERE:
if expr, err = p.parseExpr(); err != nil {
return exp, err
}
}
for _, w := range when {
switch w {
case SELECT:
exp.Select = expr
case CREATE:
exp.Create = expr
case UPDATE:
exp.Update = expr
case DELETE:
exp.Delete = expr
case RELATE:
exp.Relate = expr
}
}
if _, _, exi := p.mightBe(FOR); !exi {
break
}
}
}
return
}

View file

@ -21,7 +21,7 @@ func (p *parser) parseRemoveStatement() (Statement, error) {
}
// Inspect the next token.
tok, _, err := p.shouldBe(NAMESPACE, DATABASE, LOGIN, TOKEN, SCOPE, TABLE, RULES, FIELD, INDEX, VIEW)
tok, _, err := p.shouldBe(NAMESPACE, DATABASE, LOGIN, TOKEN, SCOPE, TABLE, FIELD, INDEX, VIEW)
switch tok {
case NAMESPACE:
@ -36,8 +36,6 @@ func (p *parser) parseRemoveStatement() (Statement, error) {
return p.parseRemoveScopeStatement()
case TABLE:
return p.parseRemoveTableStatement()
case RULES:
return p.parseRemoveRulesStatement()
case FIELD:
return p.parseRemoveFieldStatement()
case INDEX:

View file

@ -1,117 +0,0 @@
// 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) parseDefineRulesStatement() (stmt *DefineRulesStatement, err error) {
stmt = &DefineRulesStatement{}
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthDB); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(ON); err != nil {
return nil, err
}
if stmt.What, err = p.parseNames(); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(FOR); err != nil {
return nil, err
}
for {
tok, _, exi := p.mightBe(SELECT, CREATE, UPDATE, DELETE, RELATE)
if !exi {
break
}
stmt.When = append(stmt.When, tok.String())
if _, _, exi := p.mightBe(COMMA); !exi {
break
}
}
if len(stmt.When) == 0 {
return nil, &ParseError{Found: "", Expected: []string{"SELECT", "CREATE", "UPDATE", "DELETE", "RELATE"}}
}
if _, stmt.Rule, err = p.shouldBe(ACCEPT, REJECT); err != nil {
return nil, err
}
if stmt.Cond, err = p.parseCond(); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {
return nil, err
}
return
}
func (p *parser) parseRemoveRulesStatement() (stmt *RemoveRulesStatement, err error) {
stmt = &RemoveRulesStatement{}
if stmt.KV, stmt.NS, stmt.DB, err = p.o.get(AuthDB); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(ON); err != nil {
return nil, err
}
if stmt.What, err = p.parseNames(); err != nil {
return nil, err
}
if _, _, err = p.shouldBe(FOR); err != nil {
return nil, err
}
for {
tok, _, exi := p.mightBe(SELECT, CREATE, UPDATE, DELETE, RELATE)
if !exi {
break
}
stmt.When = append(stmt.When, tok.String())
if _, _, exi := p.mightBe(COMMA); !exi {
break
}
}
if len(stmt.When) == 0 {
return nil, &ParseError{Found: "", Expected: []string{"SELECT", "CREATE", "UPDATE", "DELETE", "RELATE"}}
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {
return nil, err
}
return
}

View file

@ -1600,7 +1600,7 @@ func Test_Parse_Queries_Define(t *testing.T) {
var tests = []tester{
{
sql: `DEFINE`,
err: "Found `` but expected `NAMESPACE, DATABASE, SCOPE, TABLE, RULES, FIELD, INDEX, VIEW`",
err: "Found `` but expected `NAMESPACE, DATABASE, SCOPE, TABLE, FIELD, INDEX, VIEW`",
},
// ----------------------------------------------------------------------
{
@ -1657,57 +1657,6 @@ func Test_Parse_Queries_Define(t *testing.T) {
err: "Found `something` but expected `EOF, ;`",
},
// ----------------------------------------------------------------------
{
sql: `DEFINE RULES`,
err: "Found `` but expected `ON`",
},
{
sql: `DEFINE RULES ON`,
err: "Found `` but expected `name`",
},
{
sql: `DEFINE RULES ON person`,
err: "Found `` but expected `FOR`",
},
{
sql: `DEFINE RULES ON person FOR`,
err: "Found `` but expected `SELECT, CREATE, UPDATE, DELETE, RELATE`",
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete`,
err: "Found `` but expected `ACCEPT, REJECT`",
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete ACCEPT`,
res: &Query{Statements: []Statement{&DefineRulesStatement{
KV: "*", NS: "*", DB: "*",
What: []string{"person"},
When: []string{"SELECT", "CREATE", "UPDATE", "DELETE"},
Rule: "ACCEPT",
}}},
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete ACCEPT something`,
err: "Found `something` but expected `EOF, ;`",
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete REJECT`,
res: &Query{Statements: []Statement{&DefineRulesStatement{
KV: "*", NS: "*", DB: "*",
What: []string{"person"},
When: []string{"SELECT", "CREATE", "UPDATE", "DELETE"},
Rule: "REJECT",
}}},
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete ACCEPT something`,
err: "Found `something` but expected `EOF, ;`",
},
{
sql: `DEFINE RULES ON person FOR select, create, update, delete REJECT something`,
err: "Found `something` but expected `EOF, ;`",
},
// ----------------------------------------------------------------------
{
sql: `DEFINE FIELD`,
err: "Found `` but expected `name`",
@ -2242,7 +2191,7 @@ func Test_Parse_Queries_Remove(t *testing.T) {
var tests = []tester{
{
sql: `REMOVE`,
err: "Found `` but expected `NAMESPACE, DATABASE, SCOPE, TABLE, RULES, FIELD, INDEX, VIEW`",
err: "Found `` but expected `NAMESPACE, DATABASE, SCOPE, TABLE, FIELD, INDEX, VIEW`",
},
// ----------------------------------------------------------------------
{
@ -2275,35 +2224,6 @@ func Test_Parse_Queries_Remove(t *testing.T) {
err: "Found `something` but expected `EOF, ;`",
},
// ----------------------------------------------------------------------
{
sql: `REMOVE RULES`,
err: "Found `` but expected `ON`",
},
{
sql: `REMOVE RULES ON`,
err: "Found `` but expected `name`",
},
{
sql: `REMOVE RULES ON person`,
err: "Found `` but expected `FOR`",
},
{
sql: `REMOVE RULES ON person FOR`,
err: "Found `` but expected `SELECT, CREATE, UPDATE, DELETE, RELATE`",
},
{
sql: `REMOVE RULES ON person FOR select, create, update, delete`,
res: &Query{Statements: []Statement{&RemoveRulesStatement{
KV: "*", NS: "*", DB: "*",
What: []string{"person"},
When: []string{"SELECT", "CREATE", "UPDATE", "DELETE"},
}}},
},
{
sql: `REMOVE RULES ON person FOR select, create, update, delete something`,
err: "Found `something` but expected `EOF, ;`",
},
// ----------------------------------------------------------------------
{
sql: `REMOVE FIELD`,
err: "Found `` but expected `name`",

View file

@ -26,8 +26,27 @@ func (p *parser) parseDefineTableStatement() (stmt *DefineTableStatement, err er
return nil, err
}
if tok, _, exi := p.mightBe(SCHEMAFULL, SCHEMALESS); exi && tok == SCHEMAFULL {
stmt.Full = true
for {
tok, _, exi := p.mightBe(SCHEMAFULL, SCHEMALESS, PERMISSIONS)
if !exi {
break
}
if p.is(tok, SCHEMAFULL) {
stmt.Full = true
}
if p.is(tok, SCHEMALESS) {
stmt.Full = false
}
if p.is(tok, PERMISSIONS) {
if stmt.Perm, err = p.parsePerms(); err != nil {
return nil, err
}
}
}
if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {

View file

@ -128,6 +128,7 @@ const (
FIELD
FOR
FROM
FULL
GROUP
ID
IF
@ -157,12 +158,12 @@ const (
OR
ORDER
PASSWORD
PERMISSIONS
READONLY
REJECT
RELATE
REMOVE
RETURN
RULES
SCHEMAFULL
SCHEMALESS
SCOPE
@ -292,6 +293,7 @@ var tokens = [...]string{
FIELD: "FIELD",
FOR: "FOR",
FROM: "FROM",
FULL: "FULL",
GROUP: "GROUP",
ID: "ID",
IF: "IF",
@ -320,12 +322,12 @@ var tokens = [...]string{
OR: "OR",
ORDER: "ORDER",
PASSWORD: "PASSWORD",
PERMISSIONS: "PERMISSIONS",
READONLY: "READONLY",
REJECT: "REJECT",
RELATE: "RELATE",
REMOVE: "REMOVE",
RETURN: "RETURN",
RULES: "RULES",
SCHEMAFULL: "SCHEMAFULL",
SCHEMALESS: "SCHEMALESS",
SCOPE: "SCOPE",