Skip to content

Commit

Permalink
Added query.Execute for optimized queries using indexes
Browse files Browse the repository at this point in the history
  • Loading branch information
lkarlslund committed Sep 13, 2022
1 parent e531f82 commit 6f46164
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 15 deletions.
20 changes: 5 additions & 15 deletions modules/analyze/webservicefuncs.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,14 +258,10 @@ func analysisfuncs(ws *webservice) {
}
}

includeobjects = ws.Objs.Filter(func(o *engine.Object) bool {
return includequery.Evaluate(o)
})
includeobjects = query.Execute(includequery, ws.Objs)

if excludequery != nil {
excludeobjects = ws.Objs.Filter(func(o *engine.Object) bool {
return excludequery.Evaluate(o)
})
excludeobjects = query.Execute(excludequery, ws.Objs)
}

// var methods engine.EdgeBitmap
Expand Down Expand Up @@ -333,7 +329,7 @@ func analysisfuncs(ws *webservice) {
pg.Merge(newpg)
}
}
// pg = engine.AnalyzePaths(includeobjects.Slice()[0], excludeobjects.Slice()[0], ws.Objs, combinedmethods, engine.Probability(minprobability), 1)
// pg = engine.AnalyzePaths(includeobjects.First(), excludeobjects.First(), ws.Objs, combinedmethods, engine.Probability(minprobability), 1)
} else {
opts := engine.NewAnalyzeObjectsOptions()
opts.IncludeObjects = includeobjects
Expand Down Expand Up @@ -506,16 +502,10 @@ func analysisfuncs(ws *webservice) {
}
}

includeobjects = ws.Objs.Filter(func(o *engine.Object) bool {
// Domain Admins and Enterprise Admins groups
return includequery.Evaluate(o)
})
includeobjects = query.Execute(includequery, ws.Objs)

if excludequery != nil {
excludeobjects = ws.Objs.Filter(func(o *engine.Object) bool {
// Domain Admins and Enterprise Admins groups
return excludequery.Evaluate(o)
})
excludeobjects = query.Execute(excludequery, ws.Objs)
}

var selectededges []engine.Edge
Expand Down
86 changes: 86 additions & 0 deletions modules/query/execute.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package query

import (
"sort"

"github.com/lkarlslund/adalanche/modules/engine"
)

type IndexSelectorInfo struct {
a engine.Attribute
match string
results []*engine.Object
queryIndex int
}

func Execute(q Query, ao *engine.Objects) *engine.Objects {
var potentialindexes []IndexSelectorInfo
switch t := q.(type) {
case andquery:
// Iterate over all subitems
for _, st := range t.subitems {
if qo, ok := st.(QueryOneAttribute); ok {
if sm, ok := qo.q.(hasStringMatch); ok {
// This might be in an index
potentialindexes = append(potentialindexes, IndexSelectorInfo{
a: qo.a,
match: sm.m,
})
}
}
}
case QueryOneAttribute:
qo := t
if sm, ok := qo.q.(hasStringMatch); ok {
// This might be in an index
potentialindexes = append(potentialindexes, IndexSelectorInfo{
a: qo.a,
match: sm.m,
queryIndex: -1,
})
}
}

// No optimization possible
if len(potentialindexes) == 0 {
return ao.Filter(q.Evaluate)
}

for i, potentialIndex := range potentialindexes {
index := ao.GetIndex(potentialIndex.a)
foundObjects, found := index.Lookup(engine.AttributeValueToIndex(engine.AttributeValueString(potentialIndex.match)))
if found {
potentialindexes[i].results = foundObjects
}
}

sort.Slice(potentialindexes, func(i, j int) bool {
return len(potentialindexes[i].results) < len(potentialindexes[j].results)
})

for _, foundindex := range potentialindexes {
if len(foundindex.results) != 0 {
filteredobjects := engine.NewObjects()

// best working index is first
if foundindex.queryIndex == -1 {
// not an AND query with subitems
for _, o := range foundindex.results {
filteredobjects.Add(o)
}
} else {
// can be optimized by patching out the index matched query filter (remove queryIndex item from filter)
for _, o := range foundindex.results {
if q.Evaluate(o) {
filteredobjects.Add(o)
}
}
}

return filteredobjects
}
}

// Return unoptimized filter
return ao.Filter(q.Evaluate)
}

0 comments on commit 6f46164

Please sign in to comment.