From 2e98e2617adb1715cf89c94cdc70810b142e4686 Mon Sep 17 00:00:00 2001 From: frahman5 Date: Fri, 12 Oct 2018 14:52:34 -0400 Subject: [PATCH 1/8] Added not reserved keyword. Functions for both not in and not like --- lexical/lexemes.go | 1 + lexical/lexical.go | 2 + lexical/lexical_test.go | 5 +- lexical/tokens.go | 4 ++ parser/ast.go | 8 +++ parser/parser.go | 17 ++++- parser/parser_test.go | 148 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 183 insertions(+), 2 deletions(-) diff --git a/lexical/lexemes.go b/lexical/lexemes.go index 600cfd7..1379c83 100644 --- a/lexical/lexemes.go +++ b/lexical/lexemes.go @@ -12,3 +12,4 @@ const L_IN = "in" const L_ASC = "asc" const L_DESC = "desc" const L_LIKE = "like" +const L_NOT = "not" diff --git a/lexical/lexical.go b/lexical/lexical.go index 1435254..8b3c3cb 100644 --- a/lexical/lexical.go +++ b/lexical/lexical.go @@ -220,6 +220,8 @@ func lexemeToToken(lexeme string) uint8 { return T_DESC case L_LIKE: return T_LIKE + case L_NOT: + return T_NOT } return T_ID } diff --git a/lexical/lexical_test.go b/lexical/lexical_test.go index 0907945..fa89dc6 100644 --- a/lexical/lexical_test.go +++ b/lexical/lexical_test.go @@ -127,7 +127,7 @@ func TestErrorUnrecognizeChar(t *testing.T) { func TestReservedWords(t *testing.T) { setUp() - source = "SELECT from WHEre in " + source = "SELECT from WHEre in not" char = nextChar() var token uint8 @@ -144,6 +144,9 @@ func TestReservedWords(t *testing.T) { token, _ = Token() assertToken(t, token, T_IN) + token, _ = Token() + assertToken(t, token, T_NOT) + token, _ = Token() assertToken(t, token, T_EOF) } diff --git a/lexical/tokens.go b/lexical/tokens.go index 3658347..8108bf6 100644 --- a/lexical/tokens.go +++ b/lexical/tokens.go @@ -26,6 +26,8 @@ const T_PARENTH_R = 23 const T_IN = 24 const T_ASC = 25 const T_LIKE = 26 +const T_NOT = 27 +const T_NOT_OR_T_LIKE = 28 const T_EOF = 0 const T_FUCK = 66 @@ -58,6 +60,8 @@ func allocMapTokenNames() { T_IN: "T_IN", T_EOF: "T_EOF", T_ASC: "T_ASC", + T_NOT: "T_NOT", + T_NOT_OR_T_LIKE: "T_NOT_OR_T_LIKE", } } } diff --git a/parser/ast.go b/parser/ast.go index 43c1fc3..0d61381 100644 --- a/parser/ast.go +++ b/parser/ast.go @@ -57,6 +57,7 @@ type NodeAdapterBinToConst struct { type NodeIn struct { leftValue NodeExpr rightValue NodeExpr + Not bool } type NodeEqual struct { @@ -73,6 +74,7 @@ type NodeLike struct { leftValue NodeExpr rightValue NodeExpr Pattern *regexp.Regexp + Not bool } type NodeGreater struct { @@ -129,6 +131,9 @@ func (e *NodeEmpty) Run() { } func (n *NodeIn) Assertion(lvalue string, rvalue string) bool { + if n.Not { + return !strings.Contains(rvalue, lvalue) + } return strings.Contains(rvalue, lvalue) } @@ -210,6 +215,9 @@ func (n *NodeNotEqual) LeftValue() NodeExpr { // LIKE func (n *NodeLike) Assertion(lvalue string, rvalue string) bool { + if n.Not { + return !n.Pattern.MatchString(lvalue) + } return n.Pattern.MatchString(lvalue) } diff --git a/parser/parser.go b/parser/parser.go index 7ca9e2f..bf8d50e 100644 --- a/parser/parser.go +++ b/parser/parser.go @@ -341,7 +341,7 @@ func gWC3(eating bool) (NodeExpr, error) { return expr, nil } -// where cond 'equal', 'in', 'like' and 'not equal' +// where cond 'equal', 'in', 'not in', 'like', 'not like' and 'not equal' func gWC4(eating bool) (NodeExpr, error) { if eating { token, err := lexical.Token() @@ -355,6 +355,19 @@ func gWC4(eating bool) (NodeExpr, error) { return nil, err } + var notBool bool + if look_ahead == lexical.T_NOT { + notBool = true + token, err := lexical.Token() + if err != nil { + return nil, err + } + look_ahead = token + if look_ahead != lexical.T_LIKE && look_ahead != lexical.T_IN { + return nil, throwSyntaxError(lexical.T_NOT_OR_T_LIKE, look_ahead) + } + } + switch look_ahead { case lexical.T_EQUAL: op := new(NodeEqual) @@ -387,6 +400,7 @@ func gWC4(eating bool) (NodeExpr, error) { // we don't need to compile for every row rx := strings.Replace(expr2.(*NodeLiteral).Value(), "%", "(.*)", -1) op.Pattern, err2 = regexp.Compile(rx) + op.Not = notBool return op, err2 case lexical.T_IN: op := new(NodeIn) @@ -396,6 +410,7 @@ func gWC4(eating bool) (NodeExpr, error) { return nil, err2 } op.SetRightValue(expr2) + op.Not = notBool return op, nil } diff --git a/parser/parser_test.go b/parser/parser_test.go index 66b89ab..0c4535b 100644 --- a/parser/parser_test.go +++ b/parser/parser_test.go @@ -230,6 +230,154 @@ func TestWhereWithNotEqualCompare(t *testing.T) { } } +func TestWhereWithIn(t *testing.T) { + New("Select message from commits where 'react' in message") + + ast, err := AST() + if err != nil { + t.Errorf(err.Error()) + return + } + + selectNode := ast.Child.(*NodeSelect) + w := selectNode.Where + if w == nil { + t.Errorf("should have where node") + } + + if reflect.TypeOf(w) != reflect.TypeOf(new(NodeIn)) { + t.Errorf("should be a NodeIn") + } + + notBool := w.(*NodeIn).Not + if notBool == true { + t.Errorf("Not bool should be set to false") + } + + lValue := w.LeftValue().(*NodeLiteral) + rValue := w.RightValue().(*NodeId) + if lValue.Value() != "react" { + t.Errorf("LValue should be 'react'") + } + + if rValue.Value() != "message" { + t.Errorf("RValue should be 'message'") + } + + + +} + +func TestWhereWithNotIn(t *testing.T) { + New("Select message from commits where 'react' not in message") + + ast, err := AST() + if err != nil { + t.Errorf(err.Error()) + return + } + + selectNode := ast.Child.(*NodeSelect) + w := selectNode.Where + if w == nil { + t.Errorf("should have where node") + } + + if reflect.TypeOf(w) != reflect.TypeOf(new(NodeIn)) { + t.Errorf("should be a NodeIn") + } + + notBool := w.(*NodeIn).Not + if notBool == false { + t.Errorf("Not bool should be set to true") + } + + lValue := w.LeftValue().(*NodeLiteral) + rValue := w.RightValue().(*NodeId) + if lValue.Value() != "react" { + t.Errorf("LValue should be 'react'") + } + + if rValue.Value() != "message" { + t.Errorf("RValue should be 'message'") + } + +} + +func TestWhereWithLike(t *testing.T) { + New("Select author, message from commits where message like '%B'") + + ast, err := AST() + if err != nil { + t.Errorf(err.Error()) + return + } + + selectNode := ast.Child.(*NodeSelect) + w := selectNode.Where + if w == nil { + t.Errorf("should have where node") + } + + if reflect.TypeOf(w) != reflect.TypeOf(new(NodeLike)) { + t.Errorf("should be a NodeLike") + } + + notBool := w.(*NodeLike).Not + if notBool == true { + t.Errorf("Not bool should be set to false") + } + + lValue := w.LeftValue().(*NodeId) + rValue := w.RightValue().(*NodeLiteral) + if lValue.Value() != "message" { + t.Errorf("LValue should be 'message'") + } + + es := `Rvalue should be &B` + if rValue.Value() != "%B" { + t.Errorf(es) + } + +} + +func TestWhereWithNotLike(t *testing.T) { + New("Select author, message from commits where message not like '%B'") + + ast, err := AST() + if err != nil { + t.Errorf(err.Error()) + return + } + + selectNode := ast.Child.(*NodeSelect) + w := selectNode.Where + if w == nil { + t.Errorf("should have where node") + } + + if reflect.TypeOf(w) != reflect.TypeOf(new(NodeLike)) { + t.Errorf("should be a NodeLike") + } + + notBool := w.(*NodeLike).Not + if notBool == false { + t.Errorf("Not bool should be set to true") + } + + lValue := w.LeftValue().(*NodeId) + rValue := w.RightValue().(*NodeLiteral) + if lValue.Value() != "message" { + t.Errorf("LValue should be 'message'") + } + + es := `Rvalue should be &B` + if rValue.Value() != "%B" { + t.Errorf(es) + } + +} + func TestWhereWithGreater(t *testing.T) { New("select * from commits where date > '2014-05-12 00:00:00' ") From 78ba3e823f7ae5e4226b59a2bd679b9e1618cd79 Mon Sep 17 00:00:00 2001 From: frahman5 Date: Fri, 12 Oct 2018 16:59:02 -0400 Subject: [PATCH 2/8] removed all vestiges of T_NOT_OR_T_LIKE --- .idea/gitql.iml | 8 + .idea/misc.xml | 6 + .idea/modules.xml | 8 + .idea/vcs.xml | 7 + .idea/workspace.xml | 373 ++++++++++++++++++++++++++++++++++++++++++++ lexical/tokens.go | 2 - parser/parser.go | 2 +- 7 files changed, 403 insertions(+), 3 deletions(-) create mode 100644 .idea/gitql.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml diff --git a/.idea/gitql.iml b/.idea/gitql.iml new file mode 100644 index 0000000..c956989 --- /dev/null +++ b/.idea/gitql.iml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..28a804d --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..2f166d0 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..b1f8824 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..891be41 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,373 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + T_NOT_OR_T_LIKE + Expected + SyntaxError + + + + + + + + + + + + true + DEFINITION_ORDER + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - file://$PROJECT_DIR$/lexical/lexical_test.go - 245 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From 88581f691091d4a54e3ead7ddf4a685e155ba43d Mon Sep 17 00:00:00 2001 From: Faiyam Rahman Date: Sun, 14 Oct 2018 16:34:27 -0400 Subject: [PATCH 8/8] Fixing spaces on tokens.go --- lexical/tokens.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lexical/tokens.go b/lexical/tokens.go index dbd5528..6a51461 100644 --- a/lexical/tokens.go +++ b/lexical/tokens.go @@ -59,7 +59,7 @@ func allocMapTokenNames() { T_IN: "T_IN", T_EOF: "T_EOF", T_ASC: "T_ASC", - T_NOT: "T_NOT", + T_NOT: "T_NOT", } } }