| Index: service/datastore/index.go
|
| diff --git a/service/datastore/index.go b/service/datastore/index.go
|
| index c9589f662abb904bfa27664356846313dda127e1..0f1aaca469903e6cef8ba46bda5073dbb22f61f9 100644
|
| --- a/service/datastore/index.go
|
| +++ b/service/datastore/index.go
|
| @@ -8,6 +8,8 @@ import (
|
| "bytes"
|
| )
|
|
|
| +const MaxIndexColumns = 64
|
| +
|
| type IndexDirection bool
|
|
|
| const (
|
| @@ -21,25 +23,91 @@ type IndexColumn struct {
|
| Direction IndexDirection
|
| }
|
|
|
| +func (i IndexColumn) cmp(o IndexColumn) int {
|
| + // sort ascending first
|
| + if i.Direction == ASCENDING && o.Direction == DESCENDING {
|
| + return -1
|
| + } else if i.Direction == DESCENDING && o.Direction == ASCENDING {
|
| + return 1
|
| + }
|
| + return cmpString(i.Property, o.Property)()
|
| +}
|
| +
|
| type IndexDefinition struct {
|
| Kind string
|
| Ancestor bool
|
| SortBy []IndexColumn
|
| }
|
|
|
| +// Yeah who needs templates, right?
|
| +// <flames>This is fine.</flames>
|
| +
|
| +func cmpBool(a, b bool) func() int {
|
| + return func() int {
|
| + if a == b {
|
| + return 0
|
| + }
|
| + if a && !b { // >
|
| + return 1
|
| + }
|
| + return -1
|
| + }
|
| +}
|
| +
|
| +func cmpInt(a, b int) func() int {
|
| + return func() int {
|
| + if a == b {
|
| + return 0
|
| + }
|
| + if a > b {
|
| + return 1
|
| + }
|
| + return -1
|
| + }
|
| +}
|
| +
|
| +func cmpString(a, b string) func() int {
|
| + return func() int {
|
| + if a == b {
|
| + return 0
|
| + }
|
| + if a > b {
|
| + return 1
|
| + }
|
| + return -1
|
| + }
|
| +}
|
| +
|
| func (i *IndexDefinition) Less(o *IndexDefinition) bool {
|
| - // yes, this is inefficient.... however I'm disinclined to care, because the
|
| - // actual comparison function is really ugly, and sorting IndexDefintions is
|
| - // not performance critical. If you're here because you profiled this and
|
| - // determined that it's a bottleneck, then feel free to rewrite :).
|
| - //
|
| - // At the time of writing, this function is only used during the tests of
|
| - // impl/memory and this package.
|
| - ibuf, obuf := &bytes.Buffer{}, &bytes.Buffer{}
|
| - // we know these can't return an error because we're using bytes.Buffer
|
| - _ = i.Write(ibuf)
|
| - _ = o.Write(obuf)
|
| - return bytes.Compare(ibuf.Bytes(), obuf.Bytes()) < 0
|
| + decide := func(v int) (ret, keepGoing bool) {
|
| + if v > 0 {
|
| + return false, false
|
| + }
|
| + if v < 0 {
|
| + return true, false
|
| + }
|
| + return false, true
|
| + }
|
| +
|
| + factors := []func() int{
|
| + cmpBool(i.Builtin(), o.Builtin()),
|
| + cmpString(i.Kind, o.Kind),
|
| + cmpBool(i.Ancestor, o.Ancestor),
|
| + cmpInt(len(i.SortBy), len(o.SortBy)),
|
| + }
|
| + for _, f := range factors {
|
| + ret, keepGoing := decide(f())
|
| + if !keepGoing {
|
| + return ret
|
| + }
|
| + }
|
| + for idx := range i.SortBy {
|
| + ret, keepGoing := decide(i.SortBy[idx].cmp(o.SortBy[idx]))
|
| + if !keepGoing {
|
| + return ret
|
| + }
|
| + }
|
| + return false
|
| }
|
|
|
| func (i *IndexDefinition) Builtin() bool {
|
|
|