diff --git a/sql/ast.go b/sql/ast.go index 5254ec80..c08b7344 100644 --- a/sql/ast.go +++ b/sql/ast.go @@ -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{} diff --git a/sql/cork.go b/sql/cork.go index 45444107..5bd708e5 100644 --- a/sql/cork.go +++ b/sql/cork.go @@ -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) { diff --git a/sql/define.go b/sql/define.go index 1f621e22..71f9bb98 100644 --- a/sql/define.go +++ b/sql/define.go @@ -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: diff --git a/sql/field.go b/sql/field.go index 98cf2b1f..c46fb311 100644 --- a/sql/field.go +++ b/sql/field.go @@ -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 { diff --git a/sql/perms.go b/sql/perms.go new file mode 100644 index 00000000..35bad29f --- /dev/null +++ b/sql/perms.go @@ -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 + +} diff --git a/sql/remove.go b/sql/remove.go index d2398074..72c6583e 100644 --- a/sql/remove.go +++ b/sql/remove.go @@ -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: diff --git a/sql/rules.go b/sql/rules.go deleted file mode 100644 index 02f02d3e..00000000 --- a/sql/rules.go +++ /dev/null @@ -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 - -} diff --git a/sql/sql_test.go b/sql/sql_test.go index 0c8c8b34..4db5537e 100644 --- a/sql/sql_test.go +++ b/sql/sql_test.go @@ -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`", diff --git a/sql/table.go b/sql/table.go index bedcc4eb..a73bcbfa 100644 --- a/sql/table.go +++ b/sql/table.go @@ -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 { diff --git a/sql/tokens.go b/sql/tokens.go index dff90b27..b2d1260c 100644 --- a/sql/tokens.go +++ b/sql/tokens.go @@ -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",