Skip to content

Commit

Permalink
Merge pull request #18 from globalsign/merge-development
Browse files Browse the repository at this point in the history
Merge development
  • Loading branch information
domodwyer authored Jul 26, 2017
2 parents 353e093 + 863d0d8 commit 00b0569
Show file tree
Hide file tree
Showing 9 changed files with 487 additions and 46 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,5 +46,6 @@ script:
- (cd bson && go test -check.v)
- go test -check.v -fast
- (cd txn && go test -check.v)
- make stopdb

# vim:sw=4:ts=4:et
12 changes: 9 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,23 @@ Further PR's (with tests) are welcome, but please maintain backwards compatibili
* Support majority read concerns ([details](https://github.com/globalsign/mgo/pull/2))
* Improved connection handling ([details](https://github.com/globalsign/mgo/pull/5))
* Hides SASL warnings ([details](https://github.com/globalsign/mgo/pull/7))
* Improved multi-document transaction performance ([details](https://github.com/globalsign/mgo/pull/10), [more](https://github.com/globalsign/mgo/pull/11))
* Integration tests run against newest MongoDB 3.2 releases ([details](https://github.com/globalsign/mgo/pull/4))
* Support for partial indexes ([detials](https://github.com/domodwyer/mgo/commit/5efe8eccb028238d93c222828cae4806aeae9f51))
* Fixes timezone handling ([details](https://github.com/go-mgo/mgo/pull/464))
* Integration tests run against newest MongoDB 3.2 releases ([details](https://github.com/globalsign/mgo/pull/4))
* Improved multi-document transaction performance ([details](https://github.com/globalsign/mgo/pull/10), [more](https://github.com/globalsign/mgo/pull/11), [more](https://github.com/globalsign/mgo/pull/16))
* Fixes cursor timeouts ([detials](https://jira.mongodb.org/browse/SERVER-24899))
* Support index hints and timeouts for count queries ([details](https://github.com/globalsign/mgo/pull/17))

---

### Thanks to
* @BenLubar
* @carter2000
* @cezarsa
* @eaglerayp
* @drichelson
* @eaglerayp
* @fmpwizard
* @jameinel
* @Reenjii
* @smoya
* @wgallagher
7 changes: 5 additions & 2 deletions bson/json.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"encoding/base64"
"fmt"
"strconv"
"strings"
"time"

"github.com/globalsign/mgo/internal/json"
Expand Down Expand Up @@ -156,7 +157,7 @@ func jencBinaryType(v interface{}) ([]byte, error) {
return fbytes(`{"$binary":"%s","$type":"0x%x"}`, out, in.Kind), nil
}

const jdateFormat = "2006-01-02T15:04:05.999Z"
const jdateFormat = "2006-01-02T15:04:05.999Z07:00"

func jdecDate(data []byte) (interface{}, error) {
var v struct {
Expand All @@ -170,13 +171,15 @@ func jdecDate(data []byte) (interface{}, error) {
v.S = v.Func.S
}
if v.S != "" {
var errs []string
for _, format := range []string{jdateFormat, "2006-01-02"} {
t, err := time.Parse(format, v.S)
if err == nil {
return t, nil
}
errs = append(errs, err.Error())
}
return nil, fmt.Errorf("cannot parse date: %q", v.S)
return nil, fmt.Errorf("cannot parse date: %q [%s]", v.S, strings.Join(errs, ", "))
}

var vn struct {
Expand Down
11 changes: 11 additions & 0 deletions bson/json_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,18 @@ var jsonTests = []jsonTest{
{
a: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.UTC),
b: `{"$date":"2016-05-15T01:02:03.004Z"}`,
}, {
a: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.FixedZone("CET", 60*60)),
b: `{"$date":"2016-05-15T01:02:03.004+01:00"}`,
}, {
b: `{"$date": {"$numberLong": "1002"}}`,
c: time.Date(1970, 1, 1, 0, 0, 1, 2e6, time.UTC),
}, {
b: `ISODate("2016-05-15T01:02:03.004Z")`,
c: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.UTC),
}, {
b: `ISODate("2016-05-15T01:02:03.004-07:00")`,
c: time.Date(2016, 5, 15, 1, 2, 3, 4000000, time.FixedZone("PDT", -7*60*60)),
}, {
b: `new Date(1000)`,
c: time.Date(1970, 1, 1, 0, 0, 1, 0, time.UTC),
Expand Down Expand Up @@ -180,6 +186,11 @@ func (s *S) TestJSON(c *C) {
value = zerov.Elem().Interface()
}
c.Logf("Loaded: %#v", value)
if ctime, ok := item.c.(time.Time); ok {
// time.Time must be compared with time.Time.Equal and not reflect.DeepEquals
c.Assert(ctime.Equal(value.(time.Time)), Equals, true)
continue
}
c.Assert(value, DeepEquals, item.c)
}
}
47 changes: 28 additions & 19 deletions session.go
Original file line number Diff line number Diff line change
Expand Up @@ -3281,20 +3281,23 @@ func prepareFindOp(socket *mongoSocket, op *queryOp, limit int32) bool {
}

find := findCmd{
Collection: op.collection[nameDot+1:],
Filter: op.query,
Projection: op.selector,
Sort: op.options.OrderBy,
Skip: op.skip,
Limit: limit,
MaxTimeMS: op.options.MaxTimeMS,
MaxScan: op.options.MaxScan,
Hint: op.options.Hint,
Comment: op.options.Comment,
Snapshot: op.options.Snapshot,
OplogReplay: op.flags&flagLogReplay != 0,
Collation: op.options.Collation,
ReadConcern: readLevel{level: op.readConcern},
Collection: op.collection[nameDot+1:],
Filter: op.query,
Projection: op.selector,
Sort: op.options.OrderBy,
Skip: op.skip,
Limit: limit,
MaxTimeMS: op.options.MaxTimeMS,
MaxScan: op.options.MaxScan,
Hint: op.options.Hint,
Comment: op.options.Comment,
Snapshot: op.options.Snapshot,
Collation: op.options.Collation,
Tailable: op.flags&flagTailable != 0,
AwaitData: op.flags&flagAwaitData != 0,
OplogReplay: op.flags&flagLogReplay != 0,
NoCursorTimeout: op.flags&flagNoCursorTimeout != 0,
ReadConcern: readLevel{level: op.readConcern},
}

if op.limit < 0 {
Expand Down Expand Up @@ -4083,10 +4086,12 @@ func (iter *Iter) getMoreCmd() *queryOp {
}

type countCmd struct {
Count string
Query interface{}
Limit int32 ",omitempty"
Skip int32 ",omitempty"
Count string
Query interface{}
Limit int32 ",omitempty"
Skip int32 ",omitempty"
Hint bson.D `bson:"hint,omitempty"`
MaxTimeMS int `bson:"maxTimeMS,omitempty"`
}

// Count returns the total number of documents in the result set.
Expand All @@ -4108,8 +4113,12 @@ func (q *Query) Count() (n int, err error) {
if query == nil {
query = bson.D{}
}
// not checking the error because if type assertion fails, we
// simply want a Zero bson.D
hint, _ := q.op.options.Hint.(bson.D)
result := struct{ N int }{}
err = session.DB(dbname).Run(countCmd{cname, query, limit, op.skip}, &result)
err = session.DB(dbname).Run(countCmd{cname, query, limit, op.skip, hint, op.options.MaxTimeMS}, &result)

return result.N, err
}

Expand Down
95 changes: 94 additions & 1 deletion session_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1275,6 +1275,49 @@ func (s *S) TestCountSkipLimit(c *C) {
c.Assert(n, Equals, 4)
}

func (s *S) TestCountMaxTimeMS(c *C) {
if !s.versionAtLeast(2, 6) {
c.Skip("SetMaxTime only supported in 2.6+")
}

session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
defer session.Close()

coll := session.DB("mydb").C("mycoll")

ns := make([]int, 100000)
for _, n := range ns {
err := coll.Insert(M{"n": n})
c.Assert(err, IsNil)
}
_, err = coll.Find(M{"n": M{"$gt": 1}}).SetMaxTime(1 * time.Millisecond).Count()
e := err.(*mgo.QueryError)
// We hope this query took longer than 1 ms, which triggers an error code 50
c.Assert(e.Code, Equals, 50)

}

func (s *S) TestCountHint(c *C) {
if !s.versionAtLeast(2, 6) {
c.Skip("Not implemented until mongo 2.5.5 https://jira.mongodb.org/browse/SERVER-2677")
}

session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
defer session.Close()

coll := session.DB("mydb").C("mycoll")
err = coll.Insert(M{"n": 1})
c.Assert(err, IsNil)

_, err = coll.Find(M{"n": M{"$gt": 1}}).Hint("does_not_exists").Count()
e := err.(*mgo.QueryError)
// If Hint wasn't doing anything, then Count would ignore the non existent index hint
// and return the normal ount. But we instead get an error code 2: bad hint
c.Assert(e.Code, Equals, 2)
}

func (s *S) TestQueryExplain(c *C) {
session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
Expand Down Expand Up @@ -1673,7 +1716,7 @@ func (s *S) TestResumeIter(c *C) {
c.Assert(len(batch), Equals, 0)
}

var cursorTimeout = flag.Bool("cursor-timeout", false, "Enable cursor timeout test")
var cursorTimeout = flag.Bool("cursor-timeout", false, "Enable cursor timeout tests")

func (s *S) TestFindIterCursorTimeout(c *C) {
if !*cursorTimeout {
Expand Down Expand Up @@ -1717,6 +1760,56 @@ func (s *S) TestFindIterCursorTimeout(c *C) {
c.Assert(iter.Err(), Equals, mgo.ErrCursor)
}

func (s *S) TestFindIterCursorNoTimeout(c *C) {
if !*cursorTimeout {
c.Skip("-cursor-timeout")
}
session, err := mgo.Dial("localhost:40001")
c.Assert(err, IsNil)
defer session.Close()

session.SetCursorTimeout(0)

type Doc struct {
Id int "_id"
}

coll := session.DB("test").C("test")
coll.Remove(nil)
for i := 0; i < 100; i++ {
err = coll.Insert(Doc{i})
c.Assert(err, IsNil)
}

session.SetBatch(1)
iter := coll.Find(nil).Iter()
var doc Doc
if !iter.Next(&doc) {
c.Fatalf("iterator failed to return any documents")
}

for i := 10; i > 0; i-- {
c.Logf("Sleeping... %d minutes to go...", i)
time.Sleep(1*time.Minute + 2*time.Second)
}

// Drain any existing documents that were fetched.
if !iter.Next(&doc) {
c.Fatalf("iterator failed to return previously cached document")
}
for i := 1; i < 100; i++ {
if !iter.Next(&doc) {
c.Errorf("iterator failed on iteration %d", i)
break
}
}
if iter.Next(&doc) {
c.Error("iterator returned more than 100 documents")
}

c.Assert(iter.Err(), IsNil)
}

func (s *S) TestTooManyItemsLimitBug(c *C) {
if *fast {
c.Skip("-fast")
Expand Down
Loading

0 comments on commit 00b0569

Please sign in to comment.