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

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

Issue 1355783002: Refactor keys and queries in datastore service and implementation. (Closed) Base URL: https://github.com/luci/gae.git@master
Patch Set: appease errcheck 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 | « service/datastore/reflect.go ('k') | service/datastore/serialize/serialize_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 package serialize 5 package serialize
6 6
7 import ( 7 import (
8 "bytes" 8 "bytes"
9 "errors" 9 "errors"
10 "fmt" 10 "fmt"
11 "sort" 11 "sort"
12 "time" 12 "time"
13 13
14 "github.com/luci/gae/service/blobstore" 14 "github.com/luci/gae/service/blobstore"
15 ds "github.com/luci/gae/service/datastore" 15 ds "github.com/luci/gae/service/datastore"
16 "github.com/luci/gae/service/datastore/dskey"
17 "github.com/luci/luci-go/common/cmpbin" 16 "github.com/luci/luci-go/common/cmpbin"
18 ) 17 )
19 18
20 // MaxIndexColumns is the maximum number of sort columns (e.g. sort orders) that 19 // MaxIndexColumns is the maximum number of sort columns (e.g. sort orders) that
21 // ReadIndexDefinition is willing to deserialize. 64 was chosen as 20 // ReadIndexDefinition is willing to deserialize. 64 was chosen as
22 // a likely-astronomical number. 21 // a likely-astronomical number.
23 const MaxIndexColumns = 64 22 const MaxIndexColumns = 64
24 23
25 // WritePropertyMapDeterministic allows tests to make WritePropertyMap 24 // WritePropertyMapDeterministic allows tests to make WritePropertyMap
26 // deterministic. 25 // deterministic.
(...skipping 17 matching lines...) Expand all
44 43
45 // With- and WithoutContext indicate if the serialization method should include 44 // With- and WithoutContext indicate if the serialization method should include
46 // context for Keys. See KeyContext for more information. 45 // context for Keys. See KeyContext for more information.
47 const ( 46 const (
48 WithContext KeyContext = true 47 WithContext KeyContext = true
49 WithoutContext = false 48 WithoutContext = false
50 ) 49 )
51 50
52 // WriteKey encodes a key to the buffer. If context is WithContext, then this 51 // WriteKey encodes a key to the buffer. If context is WithContext, then this
53 // encoded value will include the appid and namespace of the key. 52 // encoded value will include the appid and namespace of the key.
54 func WriteKey(buf Buffer, context KeyContext, k ds.Key) (err error) { 53 func WriteKey(buf Buffer, context KeyContext, k *ds.Key) (err error) {
55 // [appid ++ namespace]? ++ [1 ++ token]* ++ NULL 54 // [appid ++ namespace]? ++ [1 ++ token]* ++ NULL
56 defer recoverTo(&err) 55 defer recoverTo(&err)
57 » appid, namespace, toks := dskey.Split(k) 56 » appid, namespace, toks := k.Split()
58 if context == WithContext { 57 if context == WithContext {
59 panicIf(buf.WriteByte(1)) 58 panicIf(buf.WriteByte(1))
60 _, e := cmpbin.WriteString(buf, appid) 59 _, e := cmpbin.WriteString(buf, appid)
61 panicIf(e) 60 panicIf(e)
62 _, e = cmpbin.WriteString(buf, namespace) 61 _, e = cmpbin.WriteString(buf, namespace)
63 panicIf(e) 62 panicIf(e)
64 } else { 63 } else {
65 panicIf(buf.WriteByte(0)) 64 panicIf(buf.WriteByte(0))
66 } 65 }
67 for _, tok := range toks { 66 for _, tok := range toks {
68 panicIf(buf.WriteByte(1)) 67 panicIf(buf.WriteByte(1))
69 panicIf(WriteKeyTok(buf, tok)) 68 panicIf(WriteKeyTok(buf, tok))
70 } 69 }
71 return buf.WriteByte(0) 70 return buf.WriteByte(0)
72 } 71 }
73 72
74 // ReadKey deserializes a key from the buffer. The value of context must match 73 // ReadKey deserializes a key from the buffer. The value of context must match
75 // the value of context that was passed to WriteKey when the key was encoded. 74 // the value of context that was passed to WriteKey when the key was encoded.
76 // If context == WithoutContext, then the appid and namespace parameters are 75 // If context == WithoutContext, then the appid and namespace parameters are
77 // used in the decoded Key. Otherwise they're ignored. 76 // used in the decoded Key. Otherwise they're ignored.
78 func ReadKey(buf Buffer, context KeyContext, appid, namespace string) (ret ds.Ke y, err error) { 77 func ReadKey(buf Buffer, context KeyContext, appid, namespace string) (ret *ds.K ey, err error) {
79 defer recoverTo(&err) 78 defer recoverTo(&err)
80 actualCtx, e := buf.ReadByte() 79 actualCtx, e := buf.ReadByte()
81 panicIf(e) 80 panicIf(e)
82 81
83 actualAid, actualNS := "", "" 82 actualAid, actualNS := "", ""
84 if actualCtx == 1 { 83 if actualCtx == 1 {
85 actualAid, _, e = cmpbin.ReadString(buf) 84 actualAid, _, e = cmpbin.ReadString(buf)
86 panicIf(e) 85 panicIf(e)
87 actualNS, _, e = cmpbin.ReadString(buf) 86 actualNS, _, e = cmpbin.ReadString(buf)
88 panicIf(e) 87 panicIf(e)
(...skipping 21 matching lines...) Expand all
110 ReadKeyNumToksReasonableLimit) 109 ReadKeyNumToksReasonableLimit)
111 return 110 return
112 } 111 }
113 112
114 tok, e := ReadKeyTok(buf) 113 tok, e := ReadKeyTok(buf)
115 panicIf(e) 114 panicIf(e)
116 115
117 toks = append(toks, tok) 116 toks = append(toks, tok)
118 } 117 }
119 118
120 » return dskey.NewToks(actualAid, actualNS, toks), nil 119 » return ds.NewKeyToks(actualAid, actualNS, toks), nil
121 } 120 }
122 121
123 // WriteKeyTok writes a KeyTok to the buffer. You usually want WriteKey 122 // WriteKeyTok writes a KeyTok to the buffer. You usually want WriteKey
124 // instead of this. 123 // instead of this.
125 func WriteKeyTok(buf Buffer, tok ds.KeyTok) (err error) { 124 func WriteKeyTok(buf Buffer, tok ds.KeyTok) (err error) {
126 // tok.kind ++ typ ++ [tok.stringID || tok.intID] 125 // tok.kind ++ typ ++ [tok.stringID || tok.intID]
127 defer recoverTo(&err) 126 defer recoverTo(&err)
128 _, e := cmpbin.WriteString(buf, tok.Kind) 127 _, e := cmpbin.WriteString(buf, tok.Kind)
129 panicIf(e) 128 panicIf(e)
130 if tok.StringID != "" { 129 if tok.StringID != "" {
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
236 _, err = cmpbin.WriteFloat64(buf, p.Value().(float64)) 235 _, err = cmpbin.WriteFloat64(buf, p.Value().(float64))
237 case ds.PTString: 236 case ds.PTString:
238 _, err = cmpbin.WriteString(buf, p.Value().(string)) 237 _, err = cmpbin.WriteString(buf, p.Value().(string))
239 case ds.PTBytes: 238 case ds.PTBytes:
240 _, err = cmpbin.WriteBytes(buf, p.Value().([]byte)) 239 _, err = cmpbin.WriteBytes(buf, p.Value().([]byte))
241 case ds.PTTime: 240 case ds.PTTime:
242 err = WriteTime(buf, p.Value().(time.Time)) 241 err = WriteTime(buf, p.Value().(time.Time))
243 case ds.PTGeoPoint: 242 case ds.PTGeoPoint:
244 err = WriteGeoPoint(buf, p.Value().(ds.GeoPoint)) 243 err = WriteGeoPoint(buf, p.Value().(ds.GeoPoint))
245 case ds.PTKey: 244 case ds.PTKey:
246 » » err = WriteKey(buf, context, p.Value().(ds.Key)) 245 » » err = WriteKey(buf, context, p.Value().(*ds.Key))
247 case ds.PTBlobKey: 246 case ds.PTBlobKey:
248 _, err = cmpbin.WriteString(buf, string(p.Value().(blobstore.Key ))) 247 _, err = cmpbin.WriteString(buf, string(p.Value().(blobstore.Key )))
249 } 248 }
250 return 249 return
251 } 250 }
252 251
253 // ReadProperty reads a Property from the buffer. `context`, `appid`, and 252 // ReadProperty reads a Property from the buffer. `context`, `appid`, and
254 // `namespace` behave the same way they do for ReadKey, but only have an 253 // `namespace` behave the same way they do for ReadKey, but only have an
255 // effect if the decoded property has a Key value. 254 // effect if the decoded property has a Key value.
256 func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds .Property, err error) { 255 func ReadProperty(buf Buffer, context KeyContext, appid, namespace string) (p ds .Property, err error) {
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 } 367 }
369 pm[name] = props 368 pm[name] = props
370 } 369 }
371 return 370 return
372 } 371 }
373 372
374 // WriteIndexColumn writes an IndexColumn to the buffer. 373 // WriteIndexColumn writes an IndexColumn to the buffer.
375 func WriteIndexColumn(buf Buffer, c ds.IndexColumn) (err error) { 374 func WriteIndexColumn(buf Buffer, c ds.IndexColumn) (err error) {
376 defer recoverTo(&err) 375 defer recoverTo(&err)
377 376
378 » if c.Direction == ds.ASCENDING { 377 » if !c.Descending {
379 panicIf(buf.WriteByte(0)) 378 panicIf(buf.WriteByte(0))
380 } else { 379 } else {
381 panicIf(buf.WriteByte(1)) 380 panicIf(buf.WriteByte(1))
382 } 381 }
383 _, err = cmpbin.WriteString(buf, c.Property) 382 _, err = cmpbin.WriteString(buf, c.Property)
384 return 383 return
385 } 384 }
386 385
387 // ReadIndexColumn reads an IndexColumn from the buffer. 386 // ReadIndexColumn reads an IndexColumn from the buffer.
388 func ReadIndexColumn(buf Buffer) (c ds.IndexColumn, err error) { 387 func ReadIndexColumn(buf Buffer) (c ds.IndexColumn, err error) {
389 defer recoverTo(&err) 388 defer recoverTo(&err)
390 389
391 dir, err := buf.ReadByte() 390 dir, err := buf.ReadByte()
392 panicIf(err) 391 panicIf(err)
393 392
394 » switch dir { 393 » c.Descending = dir != 0
395 » case 0:
396 » » c.Direction = ds.ASCENDING
397 » default:
398 » » c.Direction = ds.DESCENDING
399 » }
400 c.Property, _, err = cmpbin.ReadString(buf) 394 c.Property, _, err = cmpbin.ReadString(buf)
401 return 395 return
402 } 396 }
403 397
404 // WriteIndexDefinition writes an IndexDefinition to the buffer 398 // WriteIndexDefinition writes an IndexDefinition to the buffer
405 func WriteIndexDefinition(buf Buffer, i ds.IndexDefinition) (err error) { 399 func WriteIndexDefinition(buf Buffer, i ds.IndexDefinition) (err error) {
406 defer recoverTo(&err) 400 defer recoverTo(&err)
407 401
408 _, err = cmpbin.WriteString(buf, i.Kind) 402 _, err = cmpbin.WriteString(buf, i.Kind)
409 panicIf(err) 403 panicIf(err)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
457 switch x := i.(type) { 451 switch x := i.(type) {
458 case ds.GeoPoint: 452 case ds.GeoPoint:
459 err = WriteGeoPoint(buf, x) 453 err = WriteGeoPoint(buf, x)
460 454
461 case ds.IndexColumn: 455 case ds.IndexColumn:
462 err = WriteIndexColumn(buf, x) 456 err = WriteIndexColumn(buf, x)
463 457
464 case ds.IndexDefinition: 458 case ds.IndexDefinition:
465 err = WriteIndexDefinition(buf, x) 459 err = WriteIndexDefinition(buf, x)
466 460
467 » case ds.Key: 461 » case *ds.Key:
468 err = WriteKey(buf, ctx, x) 462 err = WriteKey(buf, ctx, x)
469 463
470 case ds.KeyTok: 464 case ds.KeyTok:
471 err = WriteKeyTok(buf, x) 465 err = WriteKeyTok(buf, x)
472 466
473 case ds.Property: 467 case ds.Property:
474 err = WriteProperty(buf, ctx, x) 468 err = WriteProperty(buf, ctx, x)
475 469
476 case ds.PropertyMap: 470 case ds.PropertyMap:
477 err = WritePropertyMap(buf, ctx, x) 471 err = WritePropertyMap(buf, ctx, x)
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
542 } 536 }
543 } 537 }
544 538
545 func recoverTo(err *error) { 539 func recoverTo(err *error) {
546 if r := recover(); r != nil { 540 if r := recover(); r != nil {
547 if rerr := r.(parseError); rerr != nil { 541 if rerr := r.(parseError); rerr != nil {
548 *err = error(rerr) 542 *err = error(rerr)
549 } 543 }
550 } 544 }
551 } 545 }
OLDNEW
« no previous file with comments | « service/datastore/reflect.go ('k') | service/datastore/serialize/serialize_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698