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. // DefineTableStatement represents an SQL DEFINE TABLE statement.
type DefineTableStatement struct { type DefineTableStatement struct {
KV string `cork:"-" codec:"-"` KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"` NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"` DB string `cork:"-" codec:"-"`
What []string `cork:"-" codec:"-"` What []string `cork:"-" codec:"-"`
Full bool `cork:"full" codec:"full"` Full bool `cork:"full" codec:"full"`
Perm *PermExpression `cork:"perm" codec:"perm"`
} }
// RemoveTableStatement represents an SQL REMOVE TABLE statement. // RemoveTableStatement represents an SQL REMOVE TABLE statement.
@ -297,52 +298,29 @@ type RemoveTableStatement struct {
What []string `cork:"-" codec:"-"` 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 // Field
// -------------------------------------------------- // --------------------------------------------------
// DefineFieldStatement represents an SQL DEFINE FIELD statement. // DefineFieldStatement represents an SQL DEFINE FIELD statement.
type DefineFieldStatement struct { type DefineFieldStatement struct {
KV string `cork:"-" codec:"-"` KV string `cork:"-" codec:"-"`
NS string `cork:"-" codec:"-"` NS string `cork:"-" codec:"-"`
DB string `cork:"-" codec:"-"` DB string `cork:"-" codec:"-"`
Name string `cork:"name" codec:"name"` Name string `cork:"name" codec:"name"`
What []string `cork:"-" codec:"-"` What []string `cork:"-" codec:"-"`
Type string `cork:"type" codec:"type"` Type string `cork:"type" codec:"type"`
Enum []interface{} `cork:"enum" codec:"enum"` Perm *PermExpression `cork:"perm" codec:"perm"`
Code string `cork:"code" codec:"code"` Enum []interface{} `cork:"enum" codec:"enum"`
Min float64 `cork:"min" codec:"min"` Code string `cork:"code" codec:"code"`
Max float64 `cork:"max" codec:"max"` Min float64 `cork:"min" codec:"min"`
Match string `cork:"match" codec:"match"` Max float64 `cork:"max" codec:"max"`
Default interface{} `cork:"default" codec:"default"` Match string `cork:"match" codec:"match"`
Notnull bool `cork:"notnull" codec:"notnull"` Default interface{} `cork:"default" codec:"default"`
Readonly bool `cork:"readonly" codec:"readonly"` Notnull bool `cork:"notnull" codec:"notnull"`
Mandatory bool `cork:"mandatory" codec:"mandatory"` Readonly bool `cork:"readonly" codec:"readonly"`
Validate bool `cork:"validate" codec:"validate"` Mandatory bool `cork:"mandatory" codec:"mandatory"`
Validate bool `cork:"validate" codec:"validate"`
} }
// RemoveFieldStatement represents an SQL REMOVE FIELD statement. // RemoveFieldStatement represents an SQL REMOVE FIELD statement.
@ -498,6 +476,15 @@ type SubpExpression struct {
Cond Expr 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 // DiffExpression represents a JSON to DIFF
type DiffExpression struct { type DiffExpression struct {
JSON interface{} JSON interface{}

View file

@ -1298,66 +1298,6 @@ func (this *RemoveTableStatement) UnmarshalCORK(src []byte) (err error) {
return 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 // DefineFieldStatement
// -------------------------------------------------- // --------------------------------------------------
@ -1367,7 +1307,7 @@ func init() {
} }
func (this *DefineFieldStatement) ExtendCORK() byte { func (this *DefineFieldStatement) ExtendCORK() byte {
return 0x87 return 0x85
} }
func (this *DefineFieldStatement) MarshalCORK() (dst []byte, err error) { func (this *DefineFieldStatement) MarshalCORK() (dst []byte, err error) {
@ -1417,7 +1357,7 @@ func init() {
} }
func (this *RemoveFieldStatement) ExtendCORK() byte { func (this *RemoveFieldStatement) ExtendCORK() byte {
return 0x88 return 0x86
} }
func (this *RemoveFieldStatement) MarshalCORK() (dst []byte, err error) { func (this *RemoveFieldStatement) MarshalCORK() (dst []byte, err error) {
@ -1445,7 +1385,7 @@ func init() {
} }
func (this *DefineIndexStatement) ExtendCORK() byte { func (this *DefineIndexStatement) ExtendCORK() byte {
return 0x89 return 0x87
} }
func (this *DefineIndexStatement) MarshalCORK() (dst []byte, err error) { func (this *DefineIndexStatement) MarshalCORK() (dst []byte, err error) {
@ -1477,7 +1417,7 @@ func init() {
} }
func (this *RemoveIndexStatement) ExtendCORK() byte { func (this *RemoveIndexStatement) ExtendCORK() byte {
return 0x90 return 0x88
} }
func (this *RemoveIndexStatement) MarshalCORK() (dst []byte, err error) { func (this *RemoveIndexStatement) MarshalCORK() (dst []byte, err error) {
@ -1505,7 +1445,7 @@ func init() {
} }
func (this *DefineViewStatement) ExtendCORK() byte { func (this *DefineViewStatement) ExtendCORK() byte {
return 0x91 return 0x89
} }
func (this *DefineViewStatement) MarshalCORK() (dst []byte, err error) { func (this *DefineViewStatement) MarshalCORK() (dst []byte, err error) {
@ -1539,7 +1479,7 @@ func init() {
} }
func (this *RemoveViewStatement) ExtendCORK() byte { func (this *RemoveViewStatement) ExtendCORK() byte {
return 0x92 return 0x90
} }
func (this *RemoveViewStatement) MarshalCORK() (dst []byte, err error) { func (this *RemoveViewStatement) MarshalCORK() (dst []byte, err error) {

View file

@ -21,7 +21,7 @@ func (p *parser) parseDefineStatement() (Statement, error) {
} }
// Inspect the next token. // 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 { switch tok {
case NAMESPACE: case NAMESPACE:
@ -36,8 +36,6 @@ func (p *parser) parseDefineStatement() (Statement, error) {
return p.parseDefineScopeStatement() return p.parseDefineScopeStatement()
case TABLE: case TABLE:
return p.parseDefineTableStatement() return p.parseDefineTableStatement()
case RULES:
return p.parseDefineRulesStatement()
case FIELD: case FIELD:
return p.parseDefineFieldStatement() return p.parseDefineFieldStatement()
case INDEX: case INDEX:

View file

@ -36,7 +36,7 @@ func (p *parser) parseDefineFieldStatement() (stmt *DefineFieldStatement, err er
for { 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 { if !exi {
break 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 { 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. // 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 { switch tok {
case NAMESPACE: case NAMESPACE:
@ -36,8 +36,6 @@ func (p *parser) parseRemoveStatement() (Statement, error) {
return p.parseRemoveScopeStatement() return p.parseRemoveScopeStatement()
case TABLE: case TABLE:
return p.parseRemoveTableStatement() return p.parseRemoveTableStatement()
case RULES:
return p.parseRemoveRulesStatement()
case FIELD: case FIELD:
return p.parseRemoveFieldStatement() return p.parseRemoveFieldStatement()
case INDEX: 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{ var tests = []tester{
{ {
sql: `DEFINE`, 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, ;`", 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`, sql: `DEFINE FIELD`,
err: "Found `` but expected `name`", err: "Found `` but expected `name`",
@ -2242,7 +2191,7 @@ func Test_Parse_Queries_Remove(t *testing.T) {
var tests = []tester{ var tests = []tester{
{ {
sql: `REMOVE`, 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, ;`", 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`, sql: `REMOVE FIELD`,
err: "Found `` but expected `name`", err: "Found `` but expected `name`",

View file

@ -26,8 +26,27 @@ func (p *parser) parseDefineTableStatement() (stmt *DefineTableStatement, err er
return nil, err return nil, err
} }
if tok, _, exi := p.mightBe(SCHEMAFULL, SCHEMALESS); exi && tok == SCHEMAFULL { for {
stmt.Full = true
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 { if _, _, err = p.shouldBe(EOF, SEMICOLON); err != nil {

View file

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