// firstMatch executes the query q and loads the first entity into v. func firstMatch(c appengine.Context, q *datastore.Query, v interface{}) error { t := q.Limit(1).Run(c) _, err := t.Next(v) if err == datastore.Done { err = datastore.ErrNoSuchEntity } return err }
func fetchScores(c appengine.Context, q *datastore.Query, limit int) ( []*Score, error) { scores := make([]*Score, 0, limit) keys, err := q.Limit(limit).GetAll(c, &scores) if err != nil { return nil, err } for i, score := range scores { score.key = keys[i] } return scores, nil }
func scanData(ctxt appengine.Context, name string, period time.Duration, q *datastore.Query, f func(ctxt appengine.Context, kind, key string) error) { // TODO: Handle even more keys by using cursor. const chunk = 100000 keys, err := q.Limit(chunk).KeysOnly().GetAll(ctxt, nil) if err != nil { ctxt.Errorf("scandata %q: %v", name, err) return } const maxBatch = 100 for _, key := range keys { Task(ctxt, fmt.Sprintf("app.scandata.%s.%s", key.Kind(), key.StringID()), "scandata", name, key.Kind(), key.StringID()) } }
func GetAll(c appengine.Context, q *ds.Query, dst interface{}) (ds.Cursor, bool, error) { v := reflect.ValueOf(dst) if v.Kind() != reflect.Ptr || v.IsNil() { return ds.Cursor{}, false, ds.ErrInvalidEntityType } v = v.Elem() et := v.Type().Elem() if et.Kind() == reflect.Ptr { et = et.Elem() } if et.Kind() != reflect.Struct { return ds.Cursor{}, false, ds.ErrInvalidEntityType } vlen := v.Cap() it := q.Limit(vlen + 1).Run(c) hasMore := true for i := 0; i < vlen; i++ { ev := reflect.New(et) key, err := it.Next(ev.Interface()) if err == ds.Done { hasMore = false break } else if err != nil { return ds.Cursor{}, false, err } ev.Elem().FieldByName("Key").Set(reflect.ValueOf(key)) v.Set(reflect.Append(v, ev)) } cursor, err := it.Cursor() if err != nil { c.Errorf("Cursor failed: %v", err) } if hasMore { ev := reflect.New(et) if _, err := it.Next(ev.Interface()); err != nil { hasMore = false if err != ds.Done { c.Errorf("Next failed: %v", err) } } } return cursor, hasMore, nil }
func GetPage(c appengine.Context, query *datastore.Query, limit int, keysOnly bool, dst interface{}) (*Page, error) { var dv reflect.Value var mat multiArgType var elemType reflect.Type if !keysOnly { dv = reflect.ValueOf(dst) if dv.Kind() != reflect.Ptr || dv.IsNil() { return nil, datastore.ErrInvalidEntityType } dv = dv.Elem() mat, elemType = checkMultiArg(dv) if mat == multiArgTypeInvalid || mat == multiArgTypeInterface { return nil, datastore.ErrInvalidEntityType } } var keys []*datastore.Key var cursor datastore.Cursor query = query.Limit(limit + 1) if keysOnly { query = query.KeysOnly() } t := query.Run(c) more := true for i := 0; i < limit; i++ { var ev reflect.Value if !keysOnly { ev = reflect.New(elemType) } k, err := t.Next(ev.Interface()) if err == datastore.Done { more = false break } if err != nil { return nil, err } if !keysOnly { if mat != multiArgTypeStructPtr { ev = ev.Elem() } dv.Set(reflect.Append(dv, ev)) } keys = append(keys, k) } if more { var err error cursor, err = t.Cursor() if err != nil { return nil, err } var ei interface{} if !keysOnly { ei = reflect.New(elemType).Interface() } _, err = t.Next(ei) if err == datastore.Done { more = false } } return &Page{ Keys: keys, Start: cursor, More: more, }, nil }