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  }