query_impl.go 2.21 KB
Newer Older
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
1 2
package query

3 4 5 6 7 8 9 10 11 12 13
func DerivedResults(qr Results, ch <-chan Result) Results {
	return &results{
		query: qr.Query(),
		proc:  qr.Process(),
		res:   ch,
	}
}

// NaiveFilter applies a filter to the results.
func NaiveFilter(qr Results, filter Filter) Results {
	ch := make(chan Result)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
14 15
	go func() {
		defer close(ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
16
		defer qr.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
17

18 19
		for e := range qr.Next() {
			if e.Error != nil || filter.Filter(e.Entry) {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
20 21 22 23
				ch <- e
			}
		}
	}()
24 25

	return DerivedResults(qr, ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
26 27 28
}

// NaiveLimit truncates the results to a given int limit
29 30
func NaiveLimit(qr Results, limit int) Results {
	ch := make(chan Result)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
31 32
	go func() {
		defer close(ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
33
		defer qr.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
34

35 36
		l := 0
		for e := range qr.Next() {
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
37
			if e.Error != nil {
38
				ch <- e
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
39
				continue
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
40
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
41
			ch <- e
42
			l++
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
43 44 45
			if limit > 0 && l >= limit {
				break
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
46 47
		}
	}()
48 49

	return DerivedResults(qr, ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
50 51 52
}

// NaiveOffset skips a given number of results
53 54
func NaiveOffset(qr Results, offset int) Results {
	ch := make(chan Result)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
55 56
	go func() {
		defer close(ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
57
		defer qr.Close()
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
58

59 60 61 62 63
		sent := 0
		for e := range qr.Next() {
			if e.Error != nil {
				ch <- e
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
64

Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
65
			if sent < offset {
66
				sent++
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
67
				continue
68
			}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
69
			ch <- e
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
70 71
		}
	}()
72 73

	return DerivedResults(qr, ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
74 75 76 77
}

// NaiveOrder reorders results according to given Order.
// WARNING: this is the only non-stream friendly operation!
78 79 80 81 82
func NaiveOrder(qr Results, o Order) Results {
	ch := make(chan Result)
	var entries []Entry
	go func() {
		defer close(ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
83
		defer qr.Close()
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99

		for e := range qr.Next() {
			if e.Error != nil {
				ch <- e
			}

			entries = append(entries, e.Entry)
		}

		o.Sort(entries)
		for _, e := range entries {
			ch <- Result{Entry: e}
		}
	}()

	return DerivedResults(qr, ch)
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
100 101
}

102
func NaiveQueryApply(q Query, qr Results) Results {
103 104 105
	if q.Prefix != "" {
		qr = NaiveFilter(qr, FilterKeyPrefix{q.Prefix})
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
106 107 108 109 110 111
	for _, f := range q.Filters {
		qr = NaiveFilter(qr, f)
	}
	for _, o := range q.Orders {
		qr = NaiveOrder(qr, o)
	}
112 113 114 115 116 117
	if q.Offset != 0 {
		qr = NaiveOffset(qr, q.Offset)
	}
	if q.Limit != 0 {
		qr = NaiveLimit(qr, q.Offset)
	}
Juan Batiz-Benet's avatar
Juan Batiz-Benet committed
118 119 120 121 122 123 124 125 126 127
	return qr
}

func ResultEntriesFrom(keys []string, vals []interface{}) []Entry {
	re := make([]Entry, len(keys))
	for i, k := range keys {
		re[i] = Entry{Key: k, Value: vals[i]}
	}
	return re
}