From c3b81bbefc48151eb81aeb5e951b46cf8d6c70f8 Mon Sep 17 00:00:00 2001 From: Roberto Santalla Date: Tue, 5 Jun 2018 18:49:05 +0200 Subject: [PATCH] Allow passing slice pointer as an interface pointer to Iter.All (#181) * socket: only send client metadata once per socket (#105) Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Merge Development (#111) * Brings in a patch on having flusher not suppress errors. (#81) https://github.com/go-mgo/mgo/pull/360 * Fallback to JSON tags when BSON tag isn't present (#91) * Fallback to JSON tags when BSON tag isn't present Cleanup. * Add test to demonstrate tagging fallback. - Test coverage for tagging test. * socket: only send client metadata once per socket Periodic cluster synchronisation calls isMaster() which currently resends the "client" metadata every call - the spec specifies: isMaster commands issued after the initial connection handshake MUST NOT contain handshake arguments https://github.com/mongodb/specifications/blob/master/source/mongodb-handshake/handshake.rst#connection-handshake This hotfix prevents subsequent isMaster calls from sending the client metadata again - fixes #101 and fixes #103. Thanks to @changwoo-nam @qhenkart @canthefason @jyoon17 for spotting the initial issue, opening tickets, and having the problem debugged with a PoC fix before I even woke up. * Cluster abended test 254 (#100) * Add a test that mongo Server gets their abended reset as necessary. See https://github.com/go-mgo/mgo/issues/254 and https://github.com/go-mgo/mgo/pull/255/files * Include the patch from Issue 255. This brings in a test which fails without the patch, and passes with the patch. Still to be tested, manual tcpkill of a socket. * changeStream support (#97) Add $changeStream support * readme: credit @peterdeka and @steve-gray (#110) * Hotfix #120 (#136) * cluster: fix deadlock in cluster synchronisation (#120) For a impressively thorough breakdown of the problem, see: https://github.com/globalsign/mgo/issues/120#issuecomment-371699575 Huge thanks to @dvic and @KJTsanaktsidis for the report and fix. * readme: credit @dvic and @KJTsanaktsidis * Allow passing slice pointer as an interface pointer to Iter.All * Reverted to original error message, added test case for interface{} ptr --- .gitignore | 2 +- session.go | 12 ++++++++++-- session_test.go | 12 ++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index aae58a8c6..9a3120f6b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,2 @@ _harness -.vscode +.vscode \ No newline at end of file diff --git a/session.go b/session.go index 9defdab30..5723cd909 100644 --- a/session.go +++ b/session.go @@ -1453,7 +1453,6 @@ type Index struct { // Collation allows users to specify language-specific rules for string comparison, // such as rules for lettercase and accent marks. type Collation struct { - // Locale defines the collation locale. Locale string `bson:"locale"` @@ -4408,10 +4407,19 @@ func (iter *Iter) Next(result interface{}) bool { // func (iter *Iter) All(result interface{}) error { resultv := reflect.ValueOf(result) - if resultv.Kind() != reflect.Ptr || resultv.Elem().Kind() != reflect.Slice { + if resultv.Kind() != reflect.Ptr { panic("result argument must be a slice address") } + slicev := resultv.Elem() + + if slicev.Kind() == reflect.Interface { + slicev = slicev.Elem() + } + if slicev.Kind() != reflect.Slice { + panic("result argument must be a slice address") + } + slicev = slicev.Slice(0, slicev.Cap()) elemt := slicev.Type().Elem() i := 0 diff --git a/session_test.go b/session_test.go index f09018c70..08f330d91 100644 --- a/session_test.go +++ b/session_test.go @@ -453,6 +453,18 @@ func (s *S) TestInsertFindAll(c *C) { // Ensure result is backed by the originally allocated array c.Assert(&result[0], Equals, &allocd[0]) + // Re-run test destination as a pointer to interface{} + var resultInterface interface{} + + anotherslice := make([]R, 5) + resultInterface = anotherslice + err = coll.Find(nil).Sort("a").All(&resultInterface) + c.Assert(err, IsNil) + assertResult() + + // Ensure result is backed by the originally allocated array + c.Assert(&result[0], Equals, &allocd[0]) + // Non-pointer slice error f := func() { coll.Find(nil).All(result) } c.Assert(f, Panics, "result argument must be a slice address")