vendor: update all dependencies
* Update all dependencies * Remove all `[[constraint]]` from Gopkg.toml * Add in the minimum number of `[[override]]` to build * Remove go get of github.com/inconshreveable/mousetrap as it is vendored * Update docs with new policy on constraints
This commit is contained in:
+247
-55
@@ -20,11 +20,13 @@ import (
|
||||
"io"
|
||||
"math"
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"golang.org/x/net/context"
|
||||
|
||||
pb "google.golang.org/genproto/googleapis/firestore/v1beta1"
|
||||
|
||||
"cloud.google.com/go/internal/btree"
|
||||
"github.com/golang/protobuf/ptypes/wrappers"
|
||||
"google.golang.org/api/iterator"
|
||||
)
|
||||
@@ -397,6 +399,41 @@ func (q *Query) docSnapshotToCursorValues(ds *DocumentSnapshot, orders []order)
|
||||
return vals, nil
|
||||
}
|
||||
|
||||
// Returns a function that compares DocumentSnapshots according to q's ordering.
|
||||
func (q Query) compareFunc() func(d1, d2 *DocumentSnapshot) (int, error) {
|
||||
// Add implicit sorting by name, using the last specified direction.
|
||||
lastDir := Asc
|
||||
if len(q.orders) > 0 {
|
||||
lastDir = q.orders[len(q.orders)-1].dir
|
||||
}
|
||||
orders := append(q.copyOrders(), order{[]string{DocumentID}, lastDir})
|
||||
return func(d1, d2 *DocumentSnapshot) (int, error) {
|
||||
for _, ord := range orders {
|
||||
var cmp int
|
||||
if len(ord.fieldPath) == 1 && ord.fieldPath[0] == DocumentID {
|
||||
cmp = compareReferences(d1.Ref.Path, d2.Ref.Path)
|
||||
} else {
|
||||
v1, err := valueAtPath(ord.fieldPath, d1.proto.Fields)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
v2, err := valueAtPath(ord.fieldPath, d2.proto.Fields)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
cmp = compareValues(v1, v2)
|
||||
}
|
||||
if cmp != 0 {
|
||||
if ord.dir == Desc {
|
||||
cmp = -cmp
|
||||
}
|
||||
return cmp, nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
|
||||
type filter struct {
|
||||
fieldPath FieldPath
|
||||
op string
|
||||
@@ -407,6 +444,21 @@ func (f filter) toProto() (*pb.StructuredQuery_Filter, error) {
|
||||
if err := f.fieldPath.validate(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if uop, ok := unaryOpFor(f.value); ok {
|
||||
if f.op != "==" {
|
||||
return nil, fmt.Errorf("firestore: must use '==' when comparing %v", f.value)
|
||||
}
|
||||
return &pb.StructuredQuery_Filter{
|
||||
FilterType: &pb.StructuredQuery_Filter_UnaryFilter{
|
||||
UnaryFilter: &pb.StructuredQuery_UnaryFilter{
|
||||
OperandType: &pb.StructuredQuery_UnaryFilter_Field{
|
||||
Field: fref(f.fieldPath),
|
||||
},
|
||||
Op: uop,
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
var op pb.StructuredQuery_FieldFilter_Operator
|
||||
switch f.op {
|
||||
case "<":
|
||||
@@ -431,7 +483,7 @@ func (f filter) toProto() (*pb.StructuredQuery_Filter, error) {
|
||||
}
|
||||
return &pb.StructuredQuery_Filter{
|
||||
FilterType: &pb.StructuredQuery_Filter_FieldFilter{
|
||||
&pb.StructuredQuery_FieldFilter{
|
||||
FieldFilter: &pb.StructuredQuery_FieldFilter{
|
||||
Field: fref(f.fieldPath),
|
||||
Op: op,
|
||||
Value: val,
|
||||
@@ -440,6 +492,28 @@ func (f filter) toProto() (*pb.StructuredQuery_Filter, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
func unaryOpFor(value interface{}) (pb.StructuredQuery_UnaryFilter_Operator, bool) {
|
||||
switch {
|
||||
case value == nil:
|
||||
return pb.StructuredQuery_UnaryFilter_IS_NULL, true
|
||||
case isNaN(value):
|
||||
return pb.StructuredQuery_UnaryFilter_IS_NAN, true
|
||||
default:
|
||||
return pb.StructuredQuery_UnaryFilter_OPERATOR_UNSPECIFIED, false
|
||||
}
|
||||
}
|
||||
|
||||
func isNaN(x interface{}) bool {
|
||||
switch x := x.(type) {
|
||||
case float32:
|
||||
return math.IsNaN(float64(x))
|
||||
case float64:
|
||||
return math.IsNaN(x)
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
type order struct {
|
||||
fieldPath FieldPath
|
||||
dir Direction
|
||||
@@ -473,19 +547,25 @@ func trunc32(i int) int32 {
|
||||
// Documents returns an iterator over the query's resulting documents.
|
||||
func (q Query) Documents(ctx context.Context) *DocumentIterator {
|
||||
return &DocumentIterator{
|
||||
ctx: withResourceHeader(ctx, q.c.path()),
|
||||
q: &q,
|
||||
err: checkTransaction(ctx),
|
||||
iter: newQueryDocumentIterator(withResourceHeader(ctx, q.c.path()), &q, nil),
|
||||
err: checkTransaction(ctx),
|
||||
}
|
||||
}
|
||||
|
||||
// DocumentIterator is an iterator over documents returned by a query.
|
||||
type DocumentIterator struct {
|
||||
ctx context.Context
|
||||
q *Query
|
||||
tid []byte // transaction ID, if any
|
||||
streamClient pb.Firestore_RunQueryClient
|
||||
err error
|
||||
iter docIterator
|
||||
err error
|
||||
}
|
||||
|
||||
// Unexported interface so we can have two different kinds of DocumentIterator: one
|
||||
// for straight queries, and one for query snapshots. We do it this way instead of
|
||||
// making DocumentIterator an interface because in the client libraries, iterators are
|
||||
// always concrete types, and the fact that this one has two different implementations
|
||||
// is an internal detail.
|
||||
type docIterator interface {
|
||||
next() (*DocumentSnapshot, error)
|
||||
stop()
|
||||
}
|
||||
|
||||
// Next returns the next result. Its second return value is iterator.Done if there
|
||||
@@ -495,56 +575,29 @@ func (it *DocumentIterator) Next() (*DocumentSnapshot, error) {
|
||||
if it.err != nil {
|
||||
return nil, it.err
|
||||
}
|
||||
client := it.q.c
|
||||
if it.streamClient == nil {
|
||||
sq, err := it.q.toProto()
|
||||
if err != nil {
|
||||
it.err = err
|
||||
return nil, err
|
||||
}
|
||||
req := &pb.RunQueryRequest{
|
||||
Parent: it.q.parentPath,
|
||||
QueryType: &pb.RunQueryRequest_StructuredQuery{sq},
|
||||
}
|
||||
if it.tid != nil {
|
||||
req.ConsistencySelector = &pb.RunQueryRequest_Transaction{it.tid}
|
||||
}
|
||||
it.streamClient, it.err = client.c.RunQuery(it.ctx, req)
|
||||
if it.err != nil {
|
||||
return nil, it.err
|
||||
}
|
||||
}
|
||||
var res *pb.RunQueryResponse
|
||||
var err error
|
||||
for {
|
||||
res, err = it.streamClient.Recv()
|
||||
if err == io.EOF {
|
||||
err = iterator.Done
|
||||
}
|
||||
if err != nil {
|
||||
it.err = err
|
||||
return nil, it.err
|
||||
}
|
||||
if res.Document != nil {
|
||||
break
|
||||
}
|
||||
// No document => partial progress; keep receiving.
|
||||
}
|
||||
docRef, err := pathToDoc(res.Document.Name, client)
|
||||
ds, err := it.iter.next()
|
||||
if err != nil {
|
||||
it.err = err
|
||||
return nil, err
|
||||
}
|
||||
doc, err := newDocumentSnapshot(docRef, res.Document, client)
|
||||
if err != nil {
|
||||
it.err = err
|
||||
return nil, err
|
||||
return ds, err
|
||||
}
|
||||
|
||||
// Stop stops the iterator, freeing its resources.
|
||||
// Always call Stop when you are done with an iterator.
|
||||
// It is not safe to call Stop concurrently with Next.
|
||||
func (it *DocumentIterator) Stop() {
|
||||
if it.iter != nil { // possible in error cases
|
||||
it.iter.stop()
|
||||
}
|
||||
if it.err == nil {
|
||||
it.err = iterator.Done
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
// GetAll returns all the documents remaining from the iterator.
|
||||
// It is not necessary to call Stop on the iterator after calling GetAll.
|
||||
func (it *DocumentIterator) GetAll() ([]*DocumentSnapshot, error) {
|
||||
defer it.Stop()
|
||||
var docs []*DocumentSnapshot
|
||||
for {
|
||||
doc, err := it.Next()
|
||||
@@ -559,7 +612,146 @@ func (it *DocumentIterator) GetAll() ([]*DocumentSnapshot, error) {
|
||||
return docs, nil
|
||||
}
|
||||
|
||||
// TODO(jba): Does the iterator need a Stop or Close method? I don't think so--
|
||||
// I don't think the client can terminate a streaming receive except perhaps
|
||||
// by cancelling the context, and the user can do that themselves if they wish.
|
||||
// Find out for sure.
|
||||
type queryDocumentIterator struct {
|
||||
ctx context.Context
|
||||
cancel func()
|
||||
q *Query
|
||||
tid []byte // transaction ID, if any
|
||||
streamClient pb.Firestore_RunQueryClient
|
||||
}
|
||||
|
||||
func newQueryDocumentIterator(ctx context.Context, q *Query, tid []byte) *queryDocumentIterator {
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
return &queryDocumentIterator{
|
||||
ctx: ctx,
|
||||
cancel: cancel,
|
||||
q: q,
|
||||
tid: tid,
|
||||
}
|
||||
}
|
||||
|
||||
func (it *queryDocumentIterator) next() (*DocumentSnapshot, error) {
|
||||
client := it.q.c
|
||||
if it.streamClient == nil {
|
||||
sq, err := it.q.toProto()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := &pb.RunQueryRequest{
|
||||
Parent: it.q.parentPath,
|
||||
QueryType: &pb.RunQueryRequest_StructuredQuery{sq},
|
||||
}
|
||||
if it.tid != nil {
|
||||
req.ConsistencySelector = &pb.RunQueryRequest_Transaction{it.tid}
|
||||
}
|
||||
it.streamClient, err = client.c.RunQuery(it.ctx, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
var res *pb.RunQueryResponse
|
||||
var err error
|
||||
for {
|
||||
res, err = it.streamClient.Recv()
|
||||
if err == io.EOF {
|
||||
return nil, iterator.Done
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.Document != nil {
|
||||
break
|
||||
}
|
||||
// No document => partial progress; keep receiving.
|
||||
}
|
||||
docRef, err := pathToDoc(res.Document.Name, client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
doc, err := newDocumentSnapshot(docRef, res.Document, client, res.ReadTime)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return doc, nil
|
||||
}
|
||||
|
||||
func (it *queryDocumentIterator) stop() {
|
||||
it.cancel()
|
||||
}
|
||||
|
||||
// Snapshots returns an iterator over snapshots of the query. Each time the query
|
||||
// results change, a new snapshot will be generated.
|
||||
func (q Query) Snapshots(ctx context.Context) *QuerySnapshotIterator {
|
||||
ws, err := newWatchStreamForQuery(ctx, q)
|
||||
if err != nil {
|
||||
return &QuerySnapshotIterator{err: err}
|
||||
}
|
||||
return &QuerySnapshotIterator{
|
||||
Query: q,
|
||||
ws: ws,
|
||||
}
|
||||
}
|
||||
|
||||
// QuerySnapshotIterator is an iterator over snapshots of a query.
|
||||
// Call Next on the iterator to get a snapshot of the query's results each time they change.
|
||||
// Call Stop on the iterator when done.
|
||||
//
|
||||
// For an example, see Query.Snapshots.
|
||||
type QuerySnapshotIterator struct {
|
||||
// The Query used to construct this iterator.
|
||||
Query Query
|
||||
|
||||
// The time at which the most recent snapshot was obtained from Firestore.
|
||||
ReadTime time.Time
|
||||
|
||||
// The number of results in the most recent snapshot.
|
||||
Size int
|
||||
|
||||
// The changes since the previous snapshot.
|
||||
Changes []DocumentChange
|
||||
|
||||
ws *watchStream
|
||||
err error
|
||||
}
|
||||
|
||||
// Next blocks until the query's results change, then returns a DocumentIterator for
|
||||
// the current results.
|
||||
//
|
||||
// Next never returns iterator.Done unless it is called after Stop.
|
||||
func (it *QuerySnapshotIterator) Next() (*DocumentIterator, error) {
|
||||
if it.err != nil {
|
||||
return nil, it.err
|
||||
}
|
||||
btree, changes, readTime, err := it.ws.nextSnapshot()
|
||||
if err != nil {
|
||||
if err == io.EOF {
|
||||
err = iterator.Done
|
||||
}
|
||||
it.err = err
|
||||
return nil, it.err
|
||||
}
|
||||
it.Changes = changes
|
||||
it.ReadTime = readTime
|
||||
it.Size = btree.Len()
|
||||
return &DocumentIterator{
|
||||
iter: (*btreeDocumentIterator)(btree.BeforeIndex(0)),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Stop stops receiving snapshots.
|
||||
// You should always call Stop when you are done with an iterator, to free up resources.
|
||||
// It is not safe to call Stop concurrently with Next.
|
||||
func (it *QuerySnapshotIterator) Stop() {
|
||||
it.ws.stop()
|
||||
}
|
||||
|
||||
type btreeDocumentIterator btree.Iterator
|
||||
|
||||
func (it *btreeDocumentIterator) next() (*DocumentSnapshot, error) {
|
||||
if !(*btree.Iterator)(it).Next() {
|
||||
return nil, iterator.Done
|
||||
}
|
||||
return it.Key.(*DocumentSnapshot), nil
|
||||
}
|
||||
|
||||
func (*btreeDocumentIterator) stop() {}
|
||||
|
||||
Reference in New Issue
Block a user