Skip to content

Commit

Permalink
sql: do better job optimizing filters
Browse files Browse the repository at this point in the history
  • Loading branch information
dennwc committed Jan 6, 2018
1 parent e4c9155 commit 2d6d563
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 41 deletions.
106 changes: 66 additions & 40 deletions graph/sql/optimizer.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,15 +101,14 @@ func (opt *Optimizer) OptimizeShape(s shape.Shape) (shape.Shape, bool) {
}
}

func SelectValue(v quad.Value, op CmpOp) *Select {
func selectValueQuery(v quad.Value, op CmpOp) ([]Where, []Value, bool) {
if op == OpEqual {
// we can use hash to check equality
sel := Nodes([]Where{
{Field: "hash", Op: op, Value: Placeholder{}},
}, []Value{
HashOf(v),
})
return &sel
return []Where{
{Field: "hash", Op: op, Value: Placeholder{}},
}, []Value{
HashOf(v),
}, true
}
var (
where []Where
Expand Down Expand Up @@ -190,6 +189,14 @@ func SelectValue(v quad.Value, op CmpOp) *Select {
TimeVal(v),
}
default:
return nil, nil, false
}
return where, params, true
}

func SelectValue(v quad.Value, op CmpOp) *Select {
where, params, ok := selectValueQuery(v, op)
if !ok {
return nil
}
sel := Nodes(where, params)
Expand All @@ -212,24 +219,8 @@ func convRegexp(re string) string {
return re // TODO: convert regular expression
}

func (opt *Optimizer) optimizeFilters(s shape.Filter) (shape.Shape, bool) {
switch from := s.From.(type) {
case shape.AllNodes:
case Select:
if !from.isAll() {
return s, false
}
t, ok := from.From[0].(Table)
if !ok || t.Name != "nodes" {
return s, false
}
default:
return s, false
}
if len(s.Filters) != 1 {
return s, false
}
switch f := s.Filters[0].(type) {
func (opt *Optimizer) optimizeFilter(from shape.Shape, f shape.ValueFilter) ([]Where, []Value, bool) {
switch f := f.(type) {
case shape.Comparison:
var cmp CmpOp
switch f.Op {
Expand All @@ -242,25 +233,21 @@ func (opt *Optimizer) optimizeFilters(s shape.Filter) (shape.Shape, bool) {
case iterator.CompareLTE:
cmp = OpLTE
default:
return s, false
}
sel := SelectValue(f.Val, cmp)
if sel == nil {
return s, false
return nil, nil, false
}
return *sel, true
return selectValueQuery(f.Val, cmp)
case shape.Wildcard:
if opt.regexpOp == "" {
return s, false
return nil, nil, false
}
return Nodes([]Where{
{Field: "value_string", Op: opt.regexpOp, Value: Placeholder{}},
}, []Value{
StringVal(convRegexp(f.Regexp())),
}), true
return []Where{
{Field: "value_string", Op: opt.regexpOp, Value: Placeholder{}},
}, []Value{
StringVal(convRegexp(f.Regexp())),
}, true
case shape.Regexp:
if opt.regexpOp == "" {
return s, false
return nil, nil, false
}
where := []Where{
{Field: "value_string", Op: opt.regexpOp, Value: Placeholder{}},
Expand All @@ -271,12 +258,51 @@ func (opt *Optimizer) optimizeFilters(s shape.Filter) (shape.Shape, bool) {
{Field: "bnode", Op: OpIsNull},
}...)
}
return Nodes(where, []Value{
return where, []Value{
StringVal(convRegexp(f.Re.String())),
}), true
}, true
default:
return nil, nil, false
}
}
func (opt *Optimizer) optimizeFilters(s shape.Filter) (shape.Shape, bool) {
switch from := s.From.(type) {
case shape.AllNodes:
case Select:
if !from.isAll() {
return s, false
}
t, ok := from.From[0].(Table)
if !ok || t.Name != "nodes" {
return s, false
}
default:
return s, false
}
var (
where []Where
params []Value
)
left := shape.Filter{
From: s.From,
}
for _, f := range s.Filters {
if w, p, ok := opt.optimizeFilter(s.From, f); ok {
where = append(where, w...)
params = append(params, p...)
} else {
left.Filters = append(left.Filters, f)
}
}
if len(where) == 0 {
return s, false
}
sel := Nodes(where, params)
if len(left.Filters) == 0 {
return sel, true
}
left.From = sel
return left, true
}

func (opt *Optimizer) optimizeQuads(s shape.Quads) (shape.Shape, bool) {
Expand Down
6 changes: 5 additions & 1 deletion graph/sql/quadstore.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (

"github.com/cayleygraph/cayley/clog"
"github.com/cayleygraph/cayley/graph"
"github.com/cayleygraph/cayley/graph/iterator"
"github.com/cayleygraph/cayley/graph/log"
"github.com/cayleygraph/cayley/internal/lru"
"github.com/cayleygraph/cayley/quad"
Expand Down Expand Up @@ -459,7 +460,10 @@ func (qs *QuadStore) Quad(val graph.Value) quad.Quad {
}

func (qs *QuadStore) QuadIterator(d quad.Direction, val graph.Value) graph.Iterator {
v := val.(Value)
v, ok := val.(Value)
if !ok {
return iterator.NewNull()
}
sel := AllQuads("")
sel.WhereEq("", dirField(d), v)
return qs.NewIterator(sel)
Expand Down

0 comments on commit 2d6d563

Please sign in to comment.