github.com/attic-labs/noms@v0.0.0-20210827224422-e5fa29d95e8b/samples/go/nomdex/expr.go (about) 1 // Copyright 2016 Attic Labs, Inc. All rights reserved. 2 // Licensed under the Apache License, version 2.0: 3 // http://www.apache.org/licenses/LICENSE-2.0 4 5 package main 6 7 import ( 8 "bytes" 9 "fmt" 10 "io" 11 "sort" 12 13 "github.com/attic-labs/noms/go/types" 14 ) 15 16 type expr interface { 17 ranges() queryRangeSlice 18 dbgPrintTree(w io.Writer, level int) 19 indexName() string 20 iterator(im *indexManager) types.SetIterator 21 } 22 23 // logExpr represents a logical 'and' or 'or' expression between two other expressions. 24 // e.g. logExpr would represent the and/or expressions in this query: 25 // (index1 > 0 and index1 < 9) or (index1 > 100 and index < 109) 26 type logExpr struct { 27 op boolOp 28 expr1 expr 29 expr2 expr 30 idxName string 31 } 32 33 type compExpr struct { 34 idxName string 35 op compOp 36 v1 types.Value 37 } 38 39 func (le logExpr) indexName() string { 40 return le.idxName 41 } 42 43 func (le logExpr) iterator(im *indexManager) types.SetIterator { 44 if le.idxName != "" { 45 return unionizeIters(iteratorsFromRanges(im.indexes[le.idxName], le.ranges())) 46 } 47 48 i1 := le.expr1.iterator(im) 49 i2 := le.expr2.iterator(im) 50 var iter types.SetIterator 51 switch le.op { 52 case and: 53 if i1 == nil || i2 == nil { 54 return nil 55 } 56 iter = types.NewIntersectionIterator(le.expr1.iterator(im), le.expr2.iterator(im)) 57 case or: 58 if i1 == nil { 59 return i2 60 } 61 if i2 == nil { 62 return i1 63 } 64 iter = types.NewUnionIterator(le.expr1.iterator(im), le.expr2.iterator(im)) 65 } 66 return iter 67 } 68 69 func (le logExpr) ranges() (ranges queryRangeSlice) { 70 rslice1 := le.expr1.ranges() 71 rslice2 := le.expr2.ranges() 72 rslice := queryRangeSlice{} 73 74 switch le.op { 75 case and: 76 if len(rslice1) == 0 || len(rslice2) == 0 { 77 return rslice 78 } 79 for _, r1 := range rslice1 { 80 for _, r2 := range rslice2 { 81 rslice = append(rslice, r1.and(r2)...) 82 } 83 } 84 sort.Sort(rslice) 85 return rslice 86 case or: 87 if len(rslice1) == 0 { 88 return rslice2 89 } 90 if len(rslice2) == 0 { 91 return rslice1 92 } 93 for _, r1 := range rslice1 { 94 for _, r2 := range rslice2 { 95 rslice = append(rslice, r1.or(r2)...) 96 } 97 } 98 sort.Sort(rslice) 99 return rslice 100 } 101 return queryRangeSlice{} 102 } 103 104 func (le logExpr) dbgPrintTree(w io.Writer, level int) { 105 fmt.Fprintf(w, "%*s%s\n", 2*level, "", le.op) 106 if le.expr1 != nil { 107 le.expr1.dbgPrintTree(w, level+1) 108 } 109 if le.expr2 != nil { 110 le.expr2.dbgPrintTree(w, level+1) 111 } 112 } 113 114 func (re compExpr) indexName() string { 115 return re.idxName 116 } 117 118 func iteratorsFromRange(index types.Map, rd queryRange) []types.SetIterator { 119 first := true 120 iterators := []types.SetIterator{} 121 index.IterFrom(rd.lower.value, func(k, v types.Value) bool { 122 if first && rd.lower.value != nil && !rd.lower.include && rd.lower.value.Equals(k) { 123 return false 124 } 125 if rd.upper.value != nil { 126 if !rd.upper.include && rd.upper.value.Equals(k) { 127 return true 128 } 129 if rd.upper.value.Less(k) { 130 return true 131 } 132 } 133 s := v.(types.Set) 134 iterators = append(iterators, s.Iterator()) 135 return false 136 }) 137 return iterators 138 } 139 140 func iteratorsFromRanges(index types.Map, ranges queryRangeSlice) []types.SetIterator { 141 iterators := []types.SetIterator{} 142 for _, r := range ranges { 143 iterators = append(iterators, iteratorsFromRange(index, r)...) 144 } 145 return iterators 146 } 147 148 func unionizeIters(iters []types.SetIterator) types.SetIterator { 149 if len(iters) == 0 { 150 return nil 151 } 152 if len(iters) <= 1 { 153 return iters[0] 154 } 155 156 unionIters := []types.SetIterator{} 157 var iter0 types.SetIterator 158 for i, iter := range iters { 159 if i%2 == 0 { 160 iter0 = iter 161 } else { 162 unionIters = append(unionIters, types.NewUnionIterator(iter0, iter)) 163 iter0 = nil 164 } 165 } 166 if iter0 != nil { 167 unionIters = append(unionIters, iter0) 168 } 169 return unionizeIters(unionIters) 170 } 171 172 func (re compExpr) iterator(im *indexManager) types.SetIterator { 173 index := im.indexes[re.idxName] 174 iters := iteratorsFromRanges(index, re.ranges()) 175 return unionizeIters(iters) 176 } 177 178 func (re compExpr) ranges() (ranges queryRangeSlice) { 179 var r queryRange 180 switch re.op { 181 case equals: 182 e := bound{value: re.v1, include: true} 183 r = queryRange{lower: e, upper: e} 184 case gt: 185 r = queryRange{lower: bound{re.v1, false, 0}, upper: bound{nil, true, 1}} 186 case gte: 187 r = queryRange{lower: bound{re.v1, true, 0}, upper: bound{nil, true, 1}} 188 case lt: 189 r = queryRange{lower: bound{nil, true, -1}, upper: bound{re.v1, false, 0}} 190 case lte: 191 r = queryRange{lower: bound{nil, true, -1}, upper: bound{re.v1, true, 0}} 192 case ne: 193 return queryRangeSlice{ 194 {lower: bound{nil, true, -1}, upper: bound{re.v1, false, 0}}, 195 {lower: bound{re.v1, false, 0}, upper: bound{nil, true, 1}}, 196 } 197 } 198 return queryRangeSlice{r} 199 } 200 201 func (re compExpr) dbgPrintTree(w io.Writer, level int) { 202 buf := bytes.Buffer{} 203 types.WriteEncodedValue(&buf, re.v1) 204 fmt.Fprintf(w, "%*s%s %s %s\n", 2*level, "", re.idxName, re.op, buf.String()) 205 }