Beispiel #1
0
// 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
}
Beispiel #2
0
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
}
Beispiel #3
0
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())
	}
}
Beispiel #4
0
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
}
Beispiel #5
0
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
}