This repository has been archived by the owner on Mar 26, 2021. It is now read-only.
/
dependency.go
128 lines (115 loc) · 2.75 KB
/
dependency.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package db
import (
"fmt"
sparql "github.com/gtfierro/hod/lang/ast"
"reflect"
"strings"
)
// struct to hold the graph of the query plan
type dependencyGraph struct {
selectVars []string
roots []*queryTerm
// map of variable name -> resolved?
variables map[string]bool
terms []*queryTerm
}
// initializes the query plan struct
func makeDependencyGraph(q *sparql.Query) *dependencyGraph {
dg := &dependencyGraph{
selectVars: []string{},
roots: []*queryTerm{},
variables: make(map[string]bool),
}
for _, v := range q.Select.Vars {
dg.selectVars = append(dg.selectVars, v)
}
return dg
}
func (dg *dependencyGraph) dump() {
for _, r := range dg.terms {
fmt.Println(r)
}
}
// stores the state/variables for a particular triple
// from a SPARQL query
type queryTerm struct {
sparql.Triple
children []*queryTerm
variables []string
}
// initializes a queryTerm from a given Filter
func (dg *dependencyGraph) makeQueryTerm(t sparql.Triple) *queryTerm {
qt := &queryTerm{
t,
[]*queryTerm{},
[]string{},
}
if qt.Subject.IsVariable() {
dg.variables[qt.Subject.String()] = false
qt.variables = append(qt.variables, qt.Subject.String())
}
if qt.Predicates[0].Predicate.IsVariable() {
dg.variables[qt.Predicates[0].Predicate.String()] = false
qt.variables = append(qt.variables, qt.Predicates[0].Predicate.String())
}
if qt.Object.IsVariable() {
dg.variables[qt.Object.String()] = false
qt.variables = append(qt.variables, qt.Object.String())
}
return qt
}
// returns true if two query terms are equal
func (qt *queryTerm) equals(qt2 *queryTerm) bool {
return qt.Subject == qt2.Subject &&
qt.Object == qt2.Object &&
reflect.DeepEqual(qt.Predicates, qt2.Predicates)
}
func (qt *queryTerm) String() string {
return fmt.Sprintf("<%s %s %s>", qt.Subject, qt.Predicates, qt.Object)
}
func (qt *queryTerm) dump(indent int) {
fmt.Println(strings.Repeat(" ", indent), qt.String())
for _, c := range qt.children {
c.dump(indent + 1)
}
}
func (qt *queryTerm) overlap(other *queryTerm) int {
count := 0
for _, v := range qt.variables {
for _, vv := range other.variables {
if vv == v {
count++
}
}
}
return count
}
type queryTermList []*queryTerm
func (list queryTermList) Len() int {
return len(list)
}
func (list queryTermList) Swap(i, j int) {
list[i], list[j] = list[j], list[i]
}
func (list queryTermList) Less(i, j int) bool {
if len(list[i].variables) == 1 {
return true
} else if len(list[j].variables) == 1 {
return false
}
i_overlap := 0
for idx := 0; idx < i; idx++ {
if idx == j {
continue
}
i_overlap += list[i].overlap(list[idx])
}
j_overlap := 0
for idx := 0; idx < j; idx++ {
if idx == i {
continue
}
j_overlap += list[j].overlap(list[idx])
}
return i_overlap > j_overlap
}