| 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 "fmt" | 9 "fmt" |
| 10 "strings" | 10 "strings" |
| 11 |
| 12 "gopkg.in/yaml.v2" |
| 11 ) | 13 ) |
| 12 | 14 |
| 13 // IndexColumn represents a sort order for a single entity field. | 15 // IndexColumn represents a sort order for a single entity field. |
| 14 type IndexColumn struct { | 16 type IndexColumn struct { |
| 15 Property string | 17 Property string |
| 16 Descending bool | 18 Descending bool |
| 17 } | 19 } |
| 18 | 20 |
| 19 // ParseIndexColumn takes a spec in the form of /\s*-?\s*.+\s*/, and | 21 // ParseIndexColumn takes a spec in the form of /\s*-?\s*.+\s*/, and |
| 20 // returns an IndexColumn. Examples are: | 22 // returns an IndexColumn. Examples are: |
| (...skipping 21 matching lines...) Expand all Loading... |
| 42 func (i IndexColumn) cmp(o IndexColumn) int { | 44 func (i IndexColumn) cmp(o IndexColumn) int { |
| 43 // sort ascending first | 45 // sort ascending first |
| 44 if !i.Descending && o.Descending { | 46 if !i.Descending && o.Descending { |
| 45 return -1 | 47 return -1 |
| 46 } else if i.Descending && !o.Descending { | 48 } else if i.Descending && !o.Descending { |
| 47 return 1 | 49 return 1 |
| 48 } | 50 } |
| 49 return cmpString(i.Property, o.Property)() | 51 return cmpString(i.Property, o.Property)() |
| 50 } | 52 } |
| 51 | 53 |
| 54 // UnmarshalYAML deserializes a index.yml `property` into an IndexColumn. |
| 55 func (i *IndexColumn) UnmarshalYAML(unmarshal func(interface{}) error) error { |
| 56 var m map[string]string |
| 57 if err := unmarshal(&m); err != nil { |
| 58 return err |
| 59 } |
| 60 |
| 61 name, ok := m["name"] |
| 62 if !ok { |
| 63 return fmt.Errorf("datastore: missing required key `name`: %v",
m) |
| 64 } |
| 65 i.Property = name |
| 66 |
| 67 i.Descending = false // default direction is "asc" |
| 68 if v, ok := m["direction"]; ok && v == "desc" { |
| 69 i.Descending = true |
| 70 } |
| 71 |
| 72 return nil |
| 73 } |
| 74 |
| 75 // MarshalYAML serializes an IndexColumn into a index.yml `property`. |
| 76 func (i *IndexColumn) MarshalYAML() (interface{}, error) { |
| 77 direction := "asc" |
| 78 |
| 79 if i.Descending { |
| 80 direction = "desc" |
| 81 } |
| 82 |
| 83 return yaml.Marshal(map[string]string{ |
| 84 "name": i.Property, |
| 85 "direction": direction, |
| 86 }) |
| 87 } |
| 88 |
| 52 // String returns a human-readable version of this IndexColumn which is | 89 // String returns a human-readable version of this IndexColumn which is |
| 53 // compatible with ParseIndexColumn. | 90 // compatible with ParseIndexColumn. |
| 54 func (i IndexColumn) String() string { | 91 func (i IndexColumn) String() string { |
| 55 ret := "" | 92 ret := "" |
| 56 if i.Descending { | 93 if i.Descending { |
| 57 ret = "-" | 94 ret = "-" |
| 58 } | 95 } |
| 59 return ret + i.Property | 96 return ret + i.Property |
| 60 } | 97 } |
| 61 | 98 |
| 62 // GQL returns a correctly formatted Cloud Datastore GQL literal which | 99 // GQL returns a correctly formatted Cloud Datastore GQL literal which |
| 63 // is valid for the `ORDER BY` clause. | 100 // is valid for the `ORDER BY` clause. |
| 64 // | 101 // |
| 65 // The flavor of GQL that this emits is defined here: | 102 // The flavor of GQL that this emits is defined here: |
| 66 // https://cloud.google.com/datastore/docs/apis/gql/gql_reference | 103 // https://cloud.google.com/datastore/docs/apis/gql/gql_reference |
| 67 func (i IndexColumn) GQL() string { | 104 func (i IndexColumn) GQL() string { |
| 68 if i.Descending { | 105 if i.Descending { |
| 69 return gqlQuoteName(i.Property) + " DESC" | 106 return gqlQuoteName(i.Property) + " DESC" |
| 70 } | 107 } |
| 71 return gqlQuoteName(i.Property) | 108 return gqlQuoteName(i.Property) |
| 72 } | 109 } |
| 73 | 110 |
| 74 // IndexDefinition holds the parsed definition of a datastore index definition. | 111 // IndexDefinition holds the parsed definition of a datastore index definition. |
| 75 type IndexDefinition struct { | 112 type IndexDefinition struct { |
| 76 » Kind string | 113 » Kind string `yaml:"kind"` |
| 77 » Ancestor bool | 114 » Ancestor bool `yaml:"ancestor"` |
| 78 » SortBy []IndexColumn | 115 » SortBy []IndexColumn `yaml:"properties"` |
| 116 } |
| 117 |
| 118 // MarshalYAML serializes an IndexDefinition into a index.yml `index`. |
| 119 func (id *IndexDefinition) MarshalYAML() (interface{}, error) { |
| 120 » if id.Builtin() || !id.Compound() { |
| 121 » » return nil, fmt.Errorf("cannot generate YAML for %s", id) |
| 122 » } |
| 123 |
| 124 » return yaml.Marshal(map[string]interface{}{ |
| 125 » » "kind": id.Kind, |
| 126 » » "ancestor": id.Ancestor, |
| 127 » » "properties": id.SortBy, |
| 128 » }) |
| 79 } | 129 } |
| 80 | 130 |
| 81 // Equal returns true if the two IndexDefinitions are equivalent. | 131 // Equal returns true if the two IndexDefinitions are equivalent. |
| 82 func (id *IndexDefinition) Equal(o *IndexDefinition) bool { | 132 func (id *IndexDefinition) Equal(o *IndexDefinition) bool { |
| 83 if id.Kind != o.Kind || id.Ancestor != o.Ancestor || len(id.SortBy) != l
en(o.SortBy) { | 133 if id.Kind != o.Kind || id.Ancestor != o.Ancestor || len(id.SortBy) != l
en(o.SortBy) { |
| 84 return false | 134 return false |
| 85 } | 135 } |
| 86 for i, col := range id.SortBy { | 136 for i, col := range id.SortBy { |
| 87 if col != o.SortBy[i] { | 137 if col != o.SortBy[i] { |
| 88 return false | 138 return false |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 291 } | 341 } |
| 292 for _, sb := range id.SortBy { | 342 for _, sb := range id.SortBy { |
| 293 wr('/') | 343 wr('/') |
| 294 if sb.Descending { | 344 if sb.Descending { |
| 295 wr('-') | 345 wr('-') |
| 296 } | 346 } |
| 297 ws(sb.Property) | 347 ws(sb.Property) |
| 298 } | 348 } |
| 299 return ret.String() | 349 return ret.String() |
| 300 } | 350 } |
| OLD | NEW |