Skip to content

Commit

Permalink
Add 'like' functionality in where clause (#64)
Browse files Browse the repository at this point in the history
  • Loading branch information
jsixface authored and filhodanuvem committed Jan 14, 2018
1 parent fa64865 commit 6716a7a
Show file tree
Hide file tree
Showing 7 changed files with 71 additions and 8 deletions.
1 change: 1 addition & 0 deletions lexical/lexemes.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@ const L_LIMIT = "limit"
const L_IN = "in"
const L_ASC = "asc"
const L_DESC = "desc"
const L_LIKE = "like"
3 changes: 2 additions & 1 deletion lexical/lexical.go
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,8 @@ func lexemeToToken(lexeme string) uint8 {
return T_ASC
case L_DESC:
return T_DESC

case L_LIKE:
return T_LIKE
}
return T_ID
}
Expand Down
1 change: 1 addition & 0 deletions lexical/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const T_PARENTH_L = 22
const T_PARENTH_R = 23
const T_IN = 24
const T_ASC = 25
const T_LIKE = 26
const T_EOF = 0
const T_FUCK = 66

Expand Down
32 changes: 32 additions & 0 deletions parser/ast.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package parser

import (
"regexp"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -68,6 +69,12 @@ type NodeNotEqual struct {
rightValue NodeExpr
}

type NodeLike struct {
leftValue NodeExpr
rightValue NodeExpr
Pattern *regexp.Regexp
}

type NodeGreater struct {
leftValue NodeExpr
rightValue NodeExpr
Expand Down Expand Up @@ -201,6 +208,31 @@ func (n *NodeNotEqual) LeftValue() NodeExpr {
return n.leftValue
}

// LIKE
func (n *NodeLike) Assertion(lvalue string, rvalue string) bool {
return n.Pattern.MatchString(lvalue)
}

func (n *NodeLike) Operator() uint8 {
return lexical.T_LIKE
}

func (n *NodeLike) SetLeftValue(e NodeExpr) {
n.leftValue = e
}

func (n *NodeLike) SetRightValue(e NodeExpr) {
n.rightValue = e
}

func (n *NodeLike) RightValue() NodeExpr {
return n.rightValue
}

func (n *NodeLike) LeftValue() NodeExpr {
return n.leftValue
}

// GREATER
func (n *NodeGreater) Assertion(lvalue string, rvalue string) bool {
time := ExtractDate(rvalue)
Expand Down
17 changes: 16 additions & 1 deletion parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package parser

import (
"fmt"
"regexp"
"strconv"
"strings"
_ "unicode"

"github.com/cloudson/gitql/lexical"
Expand Down Expand Up @@ -339,7 +341,7 @@ func gWC3(eating bool) (NodeExpr, error) {
return expr, nil
}

// where cond 'equal', 'in' and 'not equal'
// where cond 'equal', 'in', 'like' and 'not equal'
func gWC4(eating bool) (NodeExpr, error) {
if eating {
token, err := lexical.Token()
Expand Down Expand Up @@ -373,6 +375,19 @@ func gWC4(eating bool) (NodeExpr, error) {
}
op.SetRightValue(expr2)
return op, nil
case lexical.T_LIKE:
op := new(NodeLike)
op.SetLeftValue(expr)
expr2, err2 := gWC4(true)
if err2 != nil {
return nil, err2
}
op.SetRightValue(expr2)
// Compile the regex while parsing, so that
// we don't need to compile for every row
rx := strings.Replace(expr2.(*NodeLiteral).Value(), "%", "(.*)", -1)
op.Pattern, err2 = regexp.Compile(rx)
return op, err2
case lexical.T_IN:
op := new(NodeIn)
op.SetLeftValue(expr)
Expand Down
9 changes: 9 additions & 0 deletions runtime/commits_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,14 @@ func TestSelectedFieldsCount(t *testing.T) {
}
}

func TestWhereLike(t *testing.T) {
query := "select hash, author from commits where hash like '%8813f1c5e6f5d10ef%'"
table := getTableForQuery(query, "../", t)
if len(table.rows) != 1 {
t.Errorf("Expecting 1 row. Got %d rows", len(table.rows))
}
}

func TestNotEqualsInWhereLTGT(t *testing.T) {
queryData := "select committer, hash from commits limit 1"
table := getTableForQuery(queryData, "../", t)
Expand All @@ -94,6 +102,7 @@ func TestNotEqualsInWhereLTGT(t *testing.T) {
t.Errorf("Still got the same committer as the first one. - %s", firstCommitter)
}
}

func TestNotEqualsInWhere(t *testing.T) {
queryData := "select committer, hash from commits limit 1"
table := getTableForQuery(queryData, "../", t)
Expand Down
16 changes: 10 additions & 6 deletions runtime/visitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,11 +117,13 @@ func (v *RuntimeVisitor) VisitExpr(n parser.NodeExpr) error {
case reflect.TypeOf(new(parser.NodeIn)):
g := n.(*parser.NodeIn)
return v.VisitIn(g)
case reflect.TypeOf(new(parser.NodeLike)):
g := n.(*parser.NodeLike)
return v.VisitLike(g)
case reflect.TypeOf(new(parser.NodeNotEqual)):
g := n.(*parser.NodeNotEqual)
return v.VisitNotEqual(g)
}

return nil
}

Expand All @@ -132,6 +134,13 @@ func (v *RuntimeVisitor) VisitEqual(n *parser.NodeEqual) error {
return nil
}

func (v *RuntimeVisitor) VisitLike(n *parser.NodeLike) error {
lvalue := n.LeftValue().(*parser.NodeId).Value()
rvalue := n.RightValue().(*parser.NodeLiteral).Value()
boolRegister = n.Assertion(metadata(lvalue), rvalue)
return nil
}

func (v *RuntimeVisitor) VisitNotEqual(n *parser.NodeNotEqual) error {
lvalue := n.LeftValue().(*parser.NodeId).Value()
rvalue := n.RightValue().(*parser.NodeLiteral).Value()
Expand All @@ -143,19 +152,15 @@ func (v *RuntimeVisitor) VisitGreater(n *parser.NodeGreater) error {
lvalue := n.LeftValue().(*parser.NodeId).Value()
lvalue = metadata(lvalue)
rvalue := n.RightValue().(*parser.NodeLiteral).Value()

boolRegister = n.Assertion(lvalue, rvalue)

return nil
}

func (v *RuntimeVisitor) VisitSmaller(n *parser.NodeSmaller) error {
lvalue := n.LeftValue().(*parser.NodeId).Value()
lvalue = metadata(lvalue)
rvalue := n.RightValue().(*parser.NodeLiteral).Value()

boolRegister = n.Assertion(lvalue, rvalue)

return nil
}

Expand All @@ -164,7 +169,6 @@ func (v *RuntimeVisitor) VisitOr(n *parser.NodeOr) error {
boolLeft := boolRegister
v.VisitExpr(n.RightValue())
boolRight := boolRegister

boolRegister = boolLeft || boolRight
return nil
}
Expand Down

0 comments on commit 6716a7a

Please sign in to comment.