| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package datastore | 5 package datastore |
| 6 | 6 |
| 7 import ( | 7 import ( |
| 8 "bytes" | 8 "bytes" |
| 9 ) | 9 ) |
| 10 | 10 |
| 11 const MaxIndexColumns = 64 | 11 const MaxIndexColumns = 64 |
| 12 | 12 |
| 13 type IndexDirection bool | 13 type IndexDirection bool |
| 14 | 14 |
| 15 const ( | 15 const ( |
| 16 // ASCENDING is false so that it's the default (zero) value. | 16 // ASCENDING is false so that it's the default (zero) value. |
| 17 ASCENDING IndexDirection = false | 17 ASCENDING IndexDirection = false |
| 18 DESCENDING = true | 18 DESCENDING = true |
| 19 ) | 19 ) |
| 20 | 20 |
| 21 func (i IndexDirection) String() string { |
| 22 if i == ASCENDING { |
| 23 return "ASCENDING" |
| 24 } |
| 25 return "DESCENDING" |
| 26 } |
| 27 |
| 21 type IndexColumn struct { | 28 type IndexColumn struct { |
| 22 Property string | 29 Property string |
| 23 Direction IndexDirection | 30 Direction IndexDirection |
| 24 } | 31 } |
| 25 | 32 |
| 26 func (i IndexColumn) cmp(o IndexColumn) int { | 33 func (i IndexColumn) cmp(o IndexColumn) int { |
| 27 // sort ascending first | 34 // sort ascending first |
| 28 if i.Direction == ASCENDING && o.Direction == DESCENDING { | 35 if i.Direction == ASCENDING && o.Direction == DESCENDING { |
| 29 return -1 | 36 return -1 |
| 30 } else if i.Direction == DESCENDING && o.Direction == ASCENDING { | 37 } else if i.Direction == DESCENDING && o.Direction == ASCENDING { |
| 31 return 1 | 38 return 1 |
| 32 } | 39 } |
| 33 return cmpString(i.Property, o.Property)() | 40 return cmpString(i.Property, o.Property)() |
| 34 } | 41 } |
| 35 | 42 |
| 36 type IndexDefinition struct { | 43 type IndexDefinition struct { |
| 37 Kind string | 44 Kind string |
| 38 Ancestor bool | 45 Ancestor bool |
| 39 SortBy []IndexColumn | 46 SortBy []IndexColumn |
| 40 } | 47 } |
| 41 | 48 |
| 49 func (id *IndexDefinition) Equal(o *IndexDefinition) bool { |
| 50 if id.Kind != o.Kind || id.Ancestor != o.Ancestor || len(id.SortBy) != l
en(o.SortBy) { |
| 51 return false |
| 52 } |
| 53 for i, col := range id.SortBy { |
| 54 if col != o.SortBy[i] { |
| 55 return false |
| 56 } |
| 57 } |
| 58 return true |
| 59 } |
| 60 |
| 61 // NormalizeOrder returns the normalized SortBy value for this IndexDefinition. |
| 62 // This is just appending __key__ if it's not explicitly the last field in this |
| 63 // IndexDefinition. |
| 64 func (id *IndexDefinition) Normalize() *IndexDefinition { |
| 65 if len(id.SortBy) > 0 && id.SortBy[len(id.SortBy)-1].Property == "__key_
_" { |
| 66 return id |
| 67 } |
| 68 ret := *id |
| 69 ret.SortBy = make([]IndexColumn, len(id.SortBy), len(id.SortBy)+1) |
| 70 copy(ret.SortBy, id.SortBy) |
| 71 ret.SortBy = append(ret.SortBy, IndexColumn{Property: "__key__"}) |
| 72 return &ret |
| 73 } |
| 74 |
| 75 func (id *IndexDefinition) GetFullSortOrder() []IndexColumn { |
| 76 id = id.Normalize() |
| 77 if !id.Ancestor { |
| 78 return id.SortBy |
| 79 } |
| 80 ret := make([]IndexColumn, 0, len(id.SortBy)+1) |
| 81 ret = append(ret, IndexColumn{Property: "__ancestor__"}) |
| 82 return append(ret, id.SortBy...) |
| 83 } |
| 84 |
| 85 func (id *IndexDefinition) PrepForIdxTable() *IndexDefinition { |
| 86 return id.Normalize().Flip() |
| 87 } |
| 88 |
| 89 func (id *IndexDefinition) Flip() *IndexDefinition { |
| 90 ret := *id |
| 91 ret.SortBy = make([]IndexColumn, 0, len(id.SortBy)) |
| 92 for i := len(id.SortBy) - 1; i >= 0; i-- { |
| 93 ret.SortBy = append(ret.SortBy, id.SortBy[i]) |
| 94 } |
| 95 return &ret |
| 96 } |
| 97 |
| 42 // Yeah who needs templates, right? | 98 // Yeah who needs templates, right? |
| 43 // <flames>This is fine.</flames> | 99 // <flames>This is fine.</flames> |
| 44 | 100 |
| 45 func cmpBool(a, b bool) func() int { | 101 func cmpBool(a, b bool) func() int { |
| 46 return func() int { | 102 return func() int { |
| 47 if a == b { | 103 if a == b { |
| 48 return 0 | 104 return 0 |
| 49 } | 105 } |
| 50 if a && !b { // > | 106 if a && !b { // > |
| 51 return 1 | 107 return 1 |
| (...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 112 | 168 |
| 113 func (i *IndexDefinition) Builtin() bool { | 169 func (i *IndexDefinition) Builtin() bool { |
| 114 return !i.Ancestor && len(i.SortBy) <= 1 | 170 return !i.Ancestor && len(i.SortBy) <= 1 |
| 115 } | 171 } |
| 116 | 172 |
| 117 func (i *IndexDefinition) Compound() bool { | 173 func (i *IndexDefinition) Compound() bool { |
| 118 if i.Kind == "" || len(i.SortBy) <= 1 { | 174 if i.Kind == "" || len(i.SortBy) <= 1 { |
| 119 return false | 175 return false |
| 120 } | 176 } |
| 121 for _, sb := range i.SortBy { | 177 for _, sb := range i.SortBy { |
| 122 » » if sb.Property == "" { | 178 » » if sb.Property == "" || sb.Property == "__ancestor__" { |
| 123 return false | 179 return false |
| 124 } | 180 } |
| 125 } | 181 } |
| 126 return true | 182 return true |
| 127 } | 183 } |
| 128 | 184 |
| 129 func (i *IndexDefinition) String() string { | 185 func (i *IndexDefinition) String() string { |
| 130 ret := &bytes.Buffer{} | 186 ret := &bytes.Buffer{} |
| 131 if i.Builtin() { | 187 if i.Builtin() { |
| 132 ret.WriteRune('B') | 188 ret.WriteRune('B') |
| 133 } else { | 189 } else { |
| 134 ret.WriteRune('C') | 190 ret.WriteRune('C') |
| 135 } | 191 } |
| 136 ret.WriteRune(':') | 192 ret.WriteRune(':') |
| 137 ret.WriteString(i.Kind) | 193 ret.WriteString(i.Kind) |
| 138 if i.Ancestor { | 194 if i.Ancestor { |
| 139 ret.WriteString("|A") | 195 ret.WriteString("|A") |
| 140 } | 196 } |
| 141 for _, sb := range i.SortBy { | 197 for _, sb := range i.SortBy { |
| 142 ret.WriteRune('/') | 198 ret.WriteRune('/') |
| 143 if sb.Direction == DESCENDING { | 199 if sb.Direction == DESCENDING { |
| 144 ret.WriteRune('-') | 200 ret.WriteRune('-') |
| 145 } | 201 } |
| 146 ret.WriteString(sb.Property) | 202 ret.WriteString(sb.Property) |
| 147 } | 203 } |
| 148 return ret.String() | 204 return ret.String() |
| 149 } | 205 } |
| 150 | |
| 151 func IndexBuiltinQueryPrefix() []byte { | |
| 152 return []byte{0} | |
| 153 } | |
| 154 | |
| 155 func IndexComplexQueryPrefix() []byte { | |
| 156 return []byte{1} | |
| 157 } | |
| OLD | NEW |