Esempio n. 1
0
func keyToProto(k *Key) *pb.Key {
	if k == nil {
		return nil
	}

	// TODO(jbd): Eliminate unrequired allocations.
	path := []*pb.Key_PathElement(nil)
	for {
		el := &pb.Key_PathElement{
			Kind: proto.String(k.kind),
		}
		if k.id != 0 {
			el.Id = proto.Int64(k.id)
		}
		if k.name != "" {
			el.Name = proto.String(k.name)
		}
		path = append([]*pb.Key_PathElement{el}, path...)
		if k.parent == nil {
			break
		}
		k = k.parent
	}
	key := &pb.Key{
		PathElement: path,
	}
	if k.namespace != "" {
		key.PartitionId = &pb.PartitionId{
			Namespace: proto.String(k.namespace),
		}
	}
	return key
}
Esempio n. 2
0
func propertiesToProto(key *Key, props []Property) (*pb.Entity, error) {
	e := &pb.Entity{
		Key: keyToProto(key),
	}
	indexedProps := 0
	prevMultiple := make(map[string]*pb.Property)
	for _, p := range props {
		val, err := interfaceToProto(p.Value)
		if err != "" {
			return nil, fmt.Errorf("datastore: %s for a Property with Name %q", err, p.Name)
		}
		if !p.NoIndex {
			rVal := reflect.ValueOf(p.Value)
			if rVal.Kind() == reflect.Slice && rVal.Type().Elem().Kind() != reflect.Uint8 {
				indexedProps += rVal.Len()
			} else {
				indexedProps++
			}
		}
		if indexedProps > maxIndexedProperties {
			return nil, errors.New("datastore: too many indexed properties")
		}
		switch v := p.Value.(type) {
		case string:
		case []byte:
			if len(v) > 500 && !p.NoIndex {
				return nil, fmt.Errorf("datastore: cannot index a Property with Name %q", p.Name)
			}
		}
		val.Indexed = proto.Bool(!p.NoIndex)
		if p.Multiple {
			x, ok := prevMultiple[p.Name]
			if !ok {
				x = &pb.Property{
					Name:  proto.String(p.Name),
					Value: &pb.Value{},
				}
				prevMultiple[p.Name] = x
				e.Property = append(e.Property, x)
			}
			x.Value.ListValue = append(x.Value.ListValue, val)
		} else {
			e.Property = append(e.Property, &pb.Property{
				Name:  proto.String(p.Name),
				Value: val,
			})
		}
	}
	return e, nil
}
Esempio n. 3
0
func fakeRunQuery(in *pb.RunQueryRequest, out *pb.RunQueryResponse) error {
	expectedIn := &pb.RunQueryRequest{
		Query: &pb.Query{
			Kind: []*pb.KindExpression{&pb.KindExpression{Name: proto.String("Gopher")}},
		},
	}
	if !proto.Equal(in, expectedIn) {
		return fmt.Errorf("unsupported argument: got %v want %v", in, expectedIn)
	}
	*out = pb.RunQueryResponse{
		Batch: &pb.QueryResultBatch{
			MoreResults:      pb.QueryResultBatch_NO_MORE_RESULTS.Enum(),
			EntityResultType: pb.EntityResult_FULL.Enum(),
			EntityResult: []*pb.EntityResult{
				&pb.EntityResult{
					Entity: &pb.Entity{
						Key: key1,
						Property: []*pb.Property{
							{
								Name:  proto.String("Name"),
								Value: &pb.Value{StringValue: proto.String("George")},
							},
							{
								Name: proto.String("Height"),
								Value: &pb.Value{
									IntegerValue: proto.Int64(32),
								},
							},
						},
					},
				},
				&pb.EntityResult{
					Entity: &pb.Entity{
						Key: key2,
						Property: []*pb.Property{
							{
								Name:  proto.String("Name"),
								Value: &pb.Value{StringValue: proto.String("Rufus")},
							},
							// No height for Rufus.
						},
					},
				},
			},
		},
	}
	return nil
}
Esempio n. 4
0
func interfaceToProto(iv interface{}) (p *pb.Value, errStr string) {
	val := new(pb.Value)
	switch v := iv.(type) {
	case int:
		val.IntegerValue = proto.Int64(int64(v))
	case int32:
		val.IntegerValue = proto.Int64(int64(v))
	case int64:
		val.IntegerValue = proto.Int64(v)
	case bool:
		val.BooleanValue = proto.Bool(v)
	case string:
		val.StringValue = proto.String(v)
	case float32:
		val.DoubleValue = proto.Float64(float64(v))
	case float64:
		val.DoubleValue = proto.Float64(v)
	case *Key:
		if v != nil {
			val.KeyValue = keyToProto(v)
		}
	case time.Time:
		if v.Before(minTime) || v.After(maxTime) {
			return nil, fmt.Sprintf("time value out of range")
		}
		val.TimestampMicrosecondsValue = proto.Int64(toUnixMicro(v))
	case []byte:
		val.BlobValue = v
	default:
		if iv != nil {
			return nil, fmt.Sprintf("invalid Value type %t", iv)
		}
	}
	// TODO(jbd): Support ListValue and EntityValue.
	// TODO(jbd): Support types whose underlying type is one of the types above.
	return val, ""
}
Esempio n. 5
0
	"fmt"
	"io/ioutil"
	"net/http"
	"reflect"
	"testing"

	"camlistore.org/third_party/github.com/golang/protobuf/proto"
	"google.golang.org/cloud"
	pb "google.golang.org/cloud/internal/datastore"
)

var (
	key1 = &pb.Key{
		PathElement: []*pb.Key_PathElement{
			{
				Kind: proto.String("Gopher"),
				Id:   proto.Int64(6),
			},
		},
	}
	key2 = &pb.Key{
		PathElement: []*pb.Key_PathElement{
			{
				Kind: proto.String("Gopher"),
				Id:   proto.Int64(6),
			},
			{
				Kind: proto.String("Gopher"),
				Id:   proto.Int64(8),
			},
		},
Esempio n. 6
0
// toProto converts the query to a protocol buffer.
func (q *Query) toProto(req *pb.RunQueryRequest) error {
	dst := pb.Query{}
	if len(q.projection) != 0 && q.keysOnly {
		return errors.New("datastore: query cannot both project and be keys-only")
	}
	dst.Reset()
	if q.kind != "" {
		dst.Kind = []*pb.KindExpression{&pb.KindExpression{Name: proto.String(q.kind)}}
	}
	if q.projection != nil {
		for _, propertyName := range q.projection {
			dst.Projection = append(dst.Projection, &pb.PropertyExpression{Property: &pb.PropertyReference{Name: proto.String(propertyName)}})
		}

		if q.distinct {
			for _, propertyName := range q.projection {
				dst.GroupBy = append(dst.GroupBy, &pb.PropertyReference{Name: proto.String(propertyName)})
			}
		}
	}
	if q.keysOnly {
		dst.Projection = []*pb.PropertyExpression{&pb.PropertyExpression{Property: &pb.PropertyReference{Name: proto.String(keyFieldName)}}}
	}

	var filters []*pb.Filter
	for _, qf := range q.filter {
		if qf.FieldName == "" {
			return errors.New("datastore: empty query filter field name")
		}
		v, errStr := interfaceToProto(reflect.ValueOf(qf.Value).Interface())
		if errStr != "" {
			return errors.New("datastore: bad query filter value type: " + errStr)
		}
		xf := &pb.PropertyFilter{
			Operator: operatorToProto[qf.Op],
			Property: &pb.PropertyReference{Name: proto.String(qf.FieldName)},
			Value:    v,
		}
		if xf.Operator == nil {
			return errors.New("datastore: unknown query filter operator")
		}
		filters = append(filters, &pb.Filter{PropertyFilter: xf})
	}

	if q.ancestor != nil {
		filters = append(filters, &pb.Filter{
			PropertyFilter: &pb.PropertyFilter{
				Property: &pb.PropertyReference{Name: proto.String("__key__")},
				Operator: pb.PropertyFilter_HAS_ANCESTOR.Enum(),
				Value:    &pb.Value{KeyValue: keyToProto(q.ancestor)},
			}})
	}

	if len(filters) == 1 {
		dst.Filter = filters[0]
	} else if len(filters) > 1 {
		dst.Filter = &pb.Filter{CompositeFilter: &pb.CompositeFilter{
			Operator: pb.CompositeFilter_AND.Enum(),
			Filter:   filters,
		}}
	}

	for _, qo := range q.order {
		if qo.FieldName == "" {
			return errors.New("datastore: empty query order field name")
		}
		xo := &pb.PropertyOrder{
			Property:  &pb.PropertyReference{Name: proto.String(qo.FieldName)},
			Direction: sortDirectionToProto[qo.Direction],
		}
		if xo.Direction == nil {
			return errors.New("datastore: unknown query order direction")
		}
		dst.Order = append(dst.Order, xo)
	}
	if q.limit >= 0 {
		dst.Limit = proto.Int32(q.limit)
	}
	if q.offset != 0 {
		dst.Offset = proto.Int32(q.offset)
	}
	dst.StartCursor = q.start
	dst.EndCursor = q.end

	req.Query = &dst
	return nil
}