Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(339)

Side by Side Diff: service/datastore/pls_impl.go

Issue 1336443003: Implement projection queries correctly. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: fix comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « impl/prod/raw_datastore_type_converter_test.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 // HEAVILY adapted from github.com/golang/appengine/datastore 5 // HEAVILY adapted from github.com/golang/appengine/datastore
6 6
7 package datastore 7 package datastore
8 8
9 import ( 9 import (
10 "fmt" 10 "fmt"
11 "reflect" 11 "reflect"
12 "strconv" 12 "strconv"
13 "strings" 13 "strings"
14 "sync" 14 "sync"
15 "time"
16 "unicode" 15 "unicode"
17 16
18 "github.com/luci/gae/service/blobstore"
19 "github.com/luci/luci-go/common/errors" 17 "github.com/luci/luci-go/common/errors"
20 ) 18 )
21 19
22 // Entities with more than this many indexed properties will not be saved. 20 // Entities with more than this many indexed properties will not be saved.
23 const maxIndexedProperties = 20000 21 const maxIndexedProperties = 20000
24 22
25 type structTag struct { 23 type structTag struct {
26 name string 24 name string
27 idxSetting IndexSetting 25 idxSetting IndexSetting
28 isSlice bool 26 isSlice bool
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 } 129 }
132 130
133 var slice reflect.Value 131 var slice reflect.Value
134 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 { 132 if v.Kind() == reflect.Slice && v.Type().Elem().Kind() != reflect.Uint8 {
135 slice = v 133 slice = v
136 v = reflect.New(v.Type().Elem()).Elem() 134 v = reflect.New(v.Type().Elem()).Elem()
137 } else if requireSlice { 135 } else if requireSlice {
138 return "multiple-valued property requires a slice field type" 136 return "multiple-valued property requires a slice field type"
139 } 137 }
140 138
141 pVal := p.Value()
142
143 if ret, ok := doConversion(v); ok { 139 if ret, ok := doConversion(v); ok {
144 if ret != "" { 140 if ret != "" {
145 return ret 141 return ret
146 } 142 }
147 } else { 143 } else {
148 knd := v.Kind() 144 knd := v.Kind()
149 if v.Type().Implements(typeOfKey) { 145 if v.Type().Implements(typeOfKey) {
150 knd = reflect.Interface 146 knd = reflect.Interface
151 } 147 }
148
149 project := PTNull
150 overflow := (func(interface{}) bool)(nil)
151 set := (func(interface{}))(nil)
152
152 switch knd { 153 switch knd {
153 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64: 154 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, re flect.Int64:
154 » » » x, ok := pVal.(int64) 155 » » » project = PTInt
155 » » » if !ok && pVal != nil { 156 » » » overflow = func(x interface{}) bool { return v.OverflowI nt(x.(int64)) }
156 » » » » return typeMismatchReason(pVal, v) 157 » » » set = func(x interface{}) { v.SetInt(x.(int64)) }
157 » » » }
158 » » » if v.OverflowInt(x) {
159 » » » » return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type())
160 » » » }
161 » » » v.SetInt(x)
162 case reflect.Bool: 158 case reflect.Bool:
163 » » » x, ok := pVal.(bool) 159 » » » project = PTBool
164 » » » if !ok && pVal != nil { 160 » » » set = func(x interface{}) { v.SetBool(x.(bool)) }
165 » » » » return typeMismatchReason(pVal, v)
166 » » » }
167 » » » v.SetBool(x)
168 case reflect.String: 161 case reflect.String:
169 » » » switch x := pVal.(type) { 162 » » » project = PTString
170 » » » case blobstore.Key: 163 » » » set = func(x interface{}) { v.SetString(x.(string)) }
171 » » » » v.SetString(string(x)) 164 » » case reflect.Float32, reflect.Float64:
172 » » » case string: 165 » » » project = PTFloat
173 » » » » v.SetString(x) 166 » » » overflow = func(x interface{}) bool { return v.OverflowF loat(x.(float64)) }
174 » » » default: 167 » » » set = func(x interface{}) { v.SetFloat(x.(float64)) }
175 » » » » if pVal != nil { 168 » » case reflect.Interface:
176 » » » » » return typeMismatchReason(pVal, v) 169 » » » project = PTKey
170 » » » set = func(x interface{}) {
171 » » » » if k, ok := x.(Key); ok {
172 » » » » » v.Set(reflect.ValueOf(k))
177 } 173 }
178 } 174 }
179 case reflect.Float32, reflect.Float64:
180 x, ok := pVal.(float64)
181 if !ok && pVal != nil {
182 return typeMismatchReason(pVal, v)
183 }
184 if v.OverflowFloat(x) {
185 return fmt.Sprintf("value %v overflows struct fi eld of type %v", x, v.Type())
186 }
187 v.SetFloat(x)
188 case reflect.Interface:
189 x, ok := pVal.(Key)
190 if !ok && pVal != nil {
191 return typeMismatchReason(pVal, v)
192 }
193 if x != nil {
194 v.Set(reflect.ValueOf(x))
195 }
196 case reflect.Struct: 175 case reflect.Struct:
197 switch v.Type() { 176 switch v.Type() {
198 case typeOfTime: 177 case typeOfTime:
199 » » » » x, ok := pVal.(time.Time) 178 » » » » project = PTTime
200 » » » » if !ok && pVal != nil { 179 » » » » set = func(x interface{}) { v.Set(reflect.ValueO f(x)) }
201 » » » » » return typeMismatchReason(pVal, v)
202 » » » » }
203 » » » » v.Set(reflect.ValueOf(x))
204 case typeOfGeoPoint: 180 case typeOfGeoPoint:
205 » » » » x, ok := pVal.(GeoPoint) 181 » » » » project = PTGeoPoint
206 » » » » if !ok && pVal != nil { 182 » » » » set = func(x interface{}) { v.Set(reflect.ValueO f(x)) }
207 » » » » » return typeMismatchReason(pVal, v)
208 » » » » }
209 » » » » v.Set(reflect.ValueOf(x))
210 default: 183 default:
211 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v))) 184 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(p.value, v)))
212 } 185 }
213 case reflect.Slice: 186 case reflect.Slice:
214 » » » switch x := pVal.(type) { 187 » » » project = PTBytes
215 » » » case []byte: 188 » » » set = func(x interface{}) {
216 » » » » v.SetBytes(x) 189 » » » » v.SetBytes(reflect.ValueOf(x).Bytes())
217 » » » case ByteString:
218 » » » » v.SetBytes([]byte(x))
219 » » » default:
220 » » » » panic(fmt.Errorf("helper: impossible: %s", typeM ismatchReason(pVal, v)))
221 } 190 }
222 default: 191 default:
223 » » » panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(pVal, v))) 192 » » » panic(fmt.Errorf("helper: impossible: %s", typeMismatchR eason(p.value, v)))
224 } 193 }
194
195 pVal, err := p.Project(project)
196 if err != nil {
197 return typeMismatchReason(p.value, v)
198 }
199 if overflow != nil && overflow(pVal) {
200 return fmt.Sprintf("value %v overflows struct field of t ype %v", pVal, v.Type())
201 }
202 set(pVal)
225 } 203 }
226 if slice.IsValid() { 204 if slice.IsValid() {
227 slice.Set(reflect.Append(slice, v)) 205 slice.Set(reflect.Append(slice, v))
228 } 206 }
229 return "" 207 return ""
230 } 208 }
231 209
232 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) { 210 func (p *structPLS) Save(withMeta bool) (PropertyMap, error) {
233 size := len(p.c.byName) 211 size := len(p.c.byName)
234 if withMeta { 212 if withMeta {
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
595 switch val { 573 switch val {
596 case "on", "On", "true": 574 case "on", "On", "true":
597 return true, nil 575 return true, nil
598 case "off", "Off", "false": 576 case "off", "Off", "false":
599 return false, nil 577 return false, nil
600 } 578 }
601 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val) 579 return nil, fmt.Errorf("Toggle field has bad/missing default, go t %q", val)
602 } 580 }
603 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val) 581 return nil, fmt.Errorf("helper: meta field with bad type/value %s/%q", t , val)
604 } 582 }
OLDNEW
« no previous file with comments | « impl/prod/raw_datastore_type_converter_test.go ('k') | service/datastore/pls_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698