// MongoDB does not properly sort when keys are in parallel arrays ("Executor error: BadValue cannot sort with keys
// that are parallel arrays"), so... remove any sort options that have parallel arrays (and log it)
189055
func removeParallelArraySorts(o *QueryOptions) {
	npSorts := make([]SortOption, 0, len(o.Sort))
	for i := range o.Sort {
		sort := o.Sort[i]
		isParallel := false
		for _, npSort := range npSorts {
			isParallel = isParallelArrayPath(sort.Parameter.Paths[0].Path, npSort.Parameter.Paths[0].Path)
			if isParallel {
				fmt.Printf("Cannot sub-sort on param '%s' because its path has parallel arrays with previous sort param '%s' (due to limitation in MongoDB)\n.", sort.Parameter.Name, npSort.Parameter.Name)
				break
			}
		}
		if !isParallel {
			npSorts = append(npSorts, sort)
		}
	}
	// If we ended up removing sort options, update the Options object to reflect that
	if len(o.Sort) != len(npSorts) {
		o.Sort = npSorts
	}
}
550378
func sortMapByValue(m map[string]int) PairList {
	p := make(PairList, len(m))
	i := 0
	for k, v := range m {
		p[i] = Pair{k, v}
		i++
	}
	sort.Sort(p)
	return p
}
1149579
func (mc MongoClient) ScrubAllValueDescriptors() error {
	s := mc.getSessionCopy()
	defer s.Close()

	if _, err := s.DB(mc.database.Name).C(db.ValueDescriptorCollection).RemoveAll(nil); err != nil {
		return errorMap(err)
	}
	return nil
}
377127
func leveldb_writebatch_iterate_delete(p unsafe.Pointer, k *C.char, klen C.size_t) {
	b := (*leveldb.Batch)(p)
	key := slice(unsafe.Pointer(k), int(klen))
	b.Delete(key)
}
228019
func (db *DB) XLSort(key []byte, offset int, size int, alpha bool, desc bool, sortBy []byte, sortGet [][]byte) ([][]byte, error) {
	values, err := db.LRange(key, 0, -1)

	if err != nil {
		return nil, err
	}

	return db.xsort(values, offset, size, alpha, desc, sortBy, sortGet)
}
626061
func parallelQuickSort(data sort.Interface, lo, hi int, done chan bool) {
	if hi-lo > parallelThreshold {
		// Parallel QuickSort.
		plo, phi := partition(data, lo, hi)
		partDone := make(chan bool)
		go parallelQuickSort(data, lo, plo, partDone)
		go parallelQuickSort(data, phi, hi, partDone)
		// Wait for the end of both sorts.
		<-partDone
		<-partDone
	} else {
		// Sequential QuickSort.
		sequentialQuickSort(data, lo, hi)
	}
	// Signal that it's done.
	done <- true
}
811808
func (r *SearchRequest) Sort(field string, ascending bool) *SearchRequest {
	r.searchSource = r.searchSource.Sort(field, ascending)
	return r
}
844639
func (md *mongoDumper) Dump(baseDumpDir string) error {
	if err := md.dump(baseDumpDir); err != nil {
		return errors.Trace(err)
	}

	found, err := listDatabases(baseDumpDir)
	if err != nil {
		return errors.Trace(err)
	}

	// Strip the ignored database from the dump dir.
	ignored := found.Difference(md.Targets)
	// Admin must be removed only if the mongo version is 3.x or
	// above, since 2.x will not restore properly without admin.
	if md.DBInfo.MongoVersion.NewerThan(mongo.Mongo26) == -1 {
		ignored.Remove("admin")
	}
	err = stripIgnored(ignored, baseDumpDir)
	return errors.Trace(err)
}
1053643
func Sort(g Iterator) *Immutable {
	if g, ok := g.(*Immutable); ok {
		return g
	}
	return build(g, false)
}
138031
func deleteModel(ctx context.Context, model *Model, exec Executor, list []interface{}) (int64, error) {
	// Note: you might be tempted to think that the DELETE statement
	// could have the form:
	//
	//   DELETE FROM <table> WHERE (<col1>=<val1> AND <col2>=<val2>) OR (<col1>=<val3> ...)
	//
	// This works well when the number of rows to delete is smallish,
	// but somewhere around 500 rows (or perhaps it is the size of the
	// WHERE expression), MySQL switches to an inefficient form of
	// processing this statement. The result is that batch deletions
	// would switchover from being faster than single deletions, to
	// being much slower.

	// This is unfortunately complex. How do we group by the n-1 prefix
	// of primary key columns? First off, we generate the encoded SQL
	// values for all of the primary keys. Mildly complicated because we
	// want to avoid excessive memory allocation here.

	// buf will contain all of the encoded SQL values. We keep pointers
	// into it for each of the rows and each of the keys within the
	// row. But because the underlying []byte in buf can change when we
	// append more values, we have to use integer indices instead of
	// byte slices.
	var buf bytes.Buffer
	n := len(model.delete.traversals)
	keybuf := make([]keyInfo, len(list)*n)
	rows := make([]rowInfo, len(list))
	hooks := model.delete.hooks

	for j, obj := range list {
		v := reflect.Indirect(reflect.ValueOf(obj))
		if err := hooks.pre(obj, exec); err != nil {
			return -1, err
		}
		keys := keybuf[j*n : (j+1)*n]
		for i, traversal := range model.delete.traversals {
			start := buf.Len()
			err := encodeSQLValue(&buf, v.FieldByIndex(traversal).Interface())
			if err != nil {
				return -1, err
			}
			keys[i] = keyInfo{start, buf.Len()}
		}
		rows[j].keys = keys
		rows[j].obj = obj
	}

	// We've encoded all the row keys. Now sort the rows. This will
	// allow us to easily find all of the rows that are identical for
	// the prefix of n-1 columns.
	grouper := &rowGrouper{
		n:    n,
		buf:  buf.Bytes(),
		rows: rows,
	}
	sort.Sort(grouper)

	// Buffers for the encoded vals and arguments that will be used for
	// the AND and IN expression. The buffers are the max size to
	// minimize reallocations, though it is possible we'll only use a
	// handful of values in the same batch.
	valbuf := make([]EncodedVal, len(rows)+n-1)
	argbuf := make(ValExprs, 0, len(rows))
	var inTuple ValTuple
	inTuple.Exprs = argbuf

	// Initialize the and-expr. The and-expr is reused across all
	// batches, but we change the values for each batch. The andVals are
	// the last n-1 elements of valBuf.
	andVals := valbuf[len(rows):]
	var andExpr BoolExprBuilder
	for j := 0; j < n-1; j++ {
		key := model.delete.keyColumns[j].Eq(&andVals[j])
		if j == 0 {
			andExpr = key
		} else {
			andExpr = andExpr.And(key)
		}
	}

	var count int64
	var start int
	for i := range rows {
		// Add the IN value for the current row.
		valbuf[i].Val = grouper.rowKey(i, n-1, n-1)
		inTuple.Exprs = append(inTuple.Exprs, &valbuf[i])

		// Flush the batch if this is the last row or if the and-vals (the
		// first n-1 columns) differ from the next row.
		if i == len(rows)-1 ||
			(n > 1 && grouper.compare(i, i+1, n-2) != 0) {
			b := *model.delete.deleteBuilder
			inExpr := model.delete.keyColumns[n-1].InTuple(inTuple)
			if andExpr.BoolExpr == nil {
				b.Where(inExpr)
			} else {
				// Set the and-expr values for the first n-1 columns. These
				// values are identical for the rows in the range [start,i].
				for j := 0; j < n-1; j++ {
					andVals[j].Val = grouper.rowKey(i, j, j)
				}
				b.Where(andExpr.And(inExpr))
			}

			res, err := exec.ExecContext(ctx, &b)
			if err != nil {
				return -1, err
			}

			nrows, err := res.RowsAffected()
			if err != nil {
				return -1, err
			}
			count += nrows

			// Run the hooks immediately for the objects that have been
			// deleted.
			for j := start; j <= i; j++ {
				if err := hooks.post(rows[j].obj, exec); err != nil {
					return -1, err
				}
			}

			// Reset for the next batch.
			start = i + 1
			inTuple.Exprs = argbuf
		}
	}

	return count, nil
}
850987
func (m *MongoCache) get(key string) (*Document, error) {
	keyValue := new(Document)

	query := func(c *mgo.Collection) error {
		return c.Find(bson.M{
			"_id": key,
			"expireAt": bson.M{
				"$gt": time.Now().UTC(),
			}}).One(&keyValue)
	}

	err := m.run(m.CollectionName, query)
	if err != nil {
		return nil, err
	}

	return keyValue, nil
}
310675
func (mongo *MongoDB) Count() int {
	c, _ := mongo.Collection.Count()
	return c
}
817099
func (m *MockCollection) Find(arg0 interface{}) mongo.Query {
	ret := m.ctrl.Call(m, "Find", arg0)
	ret0, _ := ret[0].(mongo.Query)
	return ret0
}
702621
func CompareValues(v1, v2 Value) int {
	switch v1 := v1.(type) {
	case Document:
		v2, ok := v2.(Document)
		if !ok {
			return -1
		} else if len(v1) != len(v2) {
			return len(v1) - len(v2)
		}
		return -1 // TODO: implement proper sorting?
	case Strings:
		v2, ok := v2.(Strings)
		if !ok {
			return -1
		} else if len(v1) != len(v2) {
			return len(v1) - len(v2)
		}
		for i := range v1 {
			if dn := CompareValues(String(v1[i]), String(v2[i])); dn != 0 {
				return dn
			}
		}
		return 0
	case Bytes:
		v2, ok := v2.(Bytes)
		if !ok {
			return -1
		}
		return bytes.Compare(v1, v2)
	case Time:
		v2, ok := v2.(Time)
		if !ok {
			return -1
		}
		t1, t2 := time.Time(v1), time.Time(v2)
		if t1.Equal(t2) {
			return 0
		} else if t1.Before(t2) {
			return -1
		}
		return +1
	case String:
		v2, ok := v2.(String)
		if !ok {
			return -1
		}
		return strings.Compare(string(v1), string(v2))
	case Int:
		v2, ok := v2.(Int)
		if !ok {
			return -1
		}
		if v1 == v2 {
			return 0
		} else if v1 < v2 {
			return -1
		}
		return +1
	case Float:
		v2, ok := v2.(Float)
		if !ok {
			return -1
		}
		if v1 == v2 {
			return 0
		} else if v1 < v2 {
			return -1
		}
		return +1
	}
	return -1
}
989171
func (db *ProtoBrokerWrapper) ListValues(key string) (keyval.ProtoKeyValIterator, error) {
	kv, err := db.ProtoBroker.ListValues(key)
	if err != nil {
		return kv, err
	}
	return &ProtoKeyValIteratorWrapper{
		ProtoKeyValIterator: kv,
		decryptData:         db.decryptData,
	}, nil
}
68739
func (m *MockQuery) Sort(arg0 ...string) mongo.Query {
	varargs := []interface{}{}
	for _, a := range arg0 {
		varargs = append(varargs, a)
	}
	ret := m.ctrl.Call(m, "Sort", varargs...)
	ret0, _ := ret[0].(mongo.Query)
	return ret0
}
1136330
func Less(orders []Order, a, b Entry) bool {
	for _, cmp := range orders {
		switch cmp.Compare(a, b) {
		case 0:
		case -1:
			return true
		case 1:
			return false
		}
	}

	// This gives us a *stable* sort for free. We don't care
	// preserving the order from the underlying datastore
	// because it's undefined.
	return a.Key < b.Key
}