Skip to content

Commit ffd2e49

Browse files
zhaomeizhaomei
authored andcommitted
findAndModify support writeConcern
1 parent 68f656d commit ffd2e49

File tree

2 files changed

+66
-10
lines changed

2 files changed

+66
-10
lines changed

session.go

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4895,18 +4895,22 @@ type findModifyCmd struct {
48954895
Collection string `bson:"findAndModify"`
48964896
Query, Update, Sort, Fields interface{} `bson:",omitempty"`
48974897
Upsert, Remove, New bool `bson:",omitempty"`
4898+
WriteConcern interface{} `bson:",omitempty"`
48984899
}
48994900

49004901
type valueResult struct {
4901-
Value bson.Raw
4902-
LastError LastError `bson:"lastErrorObject"`
4902+
Value bson.Raw
4903+
LastError LastError `bson:"lastErrorObject"`
4904+
ConcernError writeConcernError `bson:"writeConcernError"`
49034905
}
49044906

49054907
// Apply runs the findAndModify MongoDB command, which allows updating, upserting
49064908
// or removing a document matching a query and atomically returning either the old
49074909
// version (the default) or the new version of the document (when ReturnNew is true).
49084910
// If no objects are found Apply returns ErrNotFound.
49094911
//
4912+
// If the session is in safe mode, the LastError result will be returned as err.
4913+
//
49104914
// The Sort and Select query methods affect the result of Apply. In case
49114915
// multiple documents match the query, Sort enables selecting which document to
49124916
// act upon by ordering it first. Select enables retrieving only a selection
@@ -4943,15 +4947,27 @@ func (q *Query) Apply(change Change, result interface{}) (info *ChangeInfo, err
49434947
dbname := op.collection[:c]
49444948
cname := op.collection[c+1:]
49454949

4950+
// https://docs.mongodb.com/manual/reference/command/findAndModify/#dbcmd.findAndModify
4951+
session.m.RLock()
4952+
safeOp := session.safeOp
4953+
session.m.RUnlock()
4954+
var writeConcern interface{}
4955+
if safeOp == nil {
4956+
writeConcern = bson.D{{Name: "w", Value: 0}}
4957+
} else {
4958+
writeConcern = safeOp.query.(*getLastError)
4959+
}
4960+
49464961
cmd := findModifyCmd{
4947-
Collection: cname,
4948-
Update: change.Update,
4949-
Upsert: change.Upsert,
4950-
Remove: change.Remove,
4951-
New: change.ReturnNew,
4952-
Query: op.query,
4953-
Sort: op.options.OrderBy,
4954-
Fields: op.selector,
4962+
Collection: cname,
4963+
Update: change.Update,
4964+
Upsert: change.Upsert,
4965+
Remove: change.Remove,
4966+
New: change.ReturnNew,
4967+
Query: op.query,
4968+
Sort: op.options.OrderBy,
4969+
Fields: op.selector,
4970+
WriteConcern: writeConcern,
49554971
}
49564972

49574973
session = session.Clone()
@@ -4994,6 +5010,14 @@ func (q *Query) Apply(change Change, result interface{}) (info *ChangeInfo, err
49945010
} else if change.Upsert {
49955011
info.UpsertedId = lerr.UpsertedId
49965012
}
5013+
if doc.ConcernError.Code != 0 {
5014+
var lerr LastError
5015+
e := doc.ConcernError
5016+
lerr.Code = e.Code
5017+
lerr.Err = e.ErrMsg
5018+
err = &lerr
5019+
return info, err
5020+
}
49975021
return info, nil
49985022
}
49995023

session_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1370,6 +1370,38 @@ func (s *S) TestFindAndModify(c *C) {
13701370
c.Assert(info, IsNil)
13711371
}
13721372

1373+
func (s *S) TestFindAndModifyWriteConcern(c *C) {
1374+
session, err := mgo.Dial("localhost:40011")
1375+
c.Assert(err, IsNil)
1376+
defer session.Close()
1377+
1378+
coll := session.DB("mydb").C("mycoll")
1379+
err = coll.Insert(M{"fid": 42})
1380+
c.Assert(err, IsNil)
1381+
1382+
// Tweak the safety parameters to something unachievable.
1383+
session.SetSafe(&mgo.Safe{W: 4, WTimeout: 100})
1384+
1385+
var ret struct {
1386+
Id uint64 `bson:"id"`
1387+
}
1388+
1389+
change := mgo.Change{
1390+
Update: M{"$inc": M{"id": 8}},
1391+
ReturnNew: false,
1392+
}
1393+
info, err := coll.Find(M{"id": M{"$exists": true}}).Apply(change, &ret)
1394+
c.Assert(err, ErrorMatches, "timeout|timed out waiting for slaves|Not enough data-bearing nodes|waiting for replication timed out")
1395+
if !s.versionAtLeast(2, 6) {
1396+
// 2.6 turned it into a query error.
1397+
c.Assert(err.(*mgo.LastError).WTimeout, Equals, true)
1398+
}
1399+
c.Assert(info.Updated, Equals, 1)
1400+
c.Assert(info.Matched, Equals, 1)
1401+
c.Assert(info.UpsertedId, NotNil)
1402+
c.Assert(ret.Id, Equals, 50)
1403+
}
1404+
13731405
func (s *S) TestFindAndModifyBug997828(c *C) {
13741406
session, err := mgo.Dial("localhost:40001")
13751407
c.Assert(err, IsNil)

0 commit comments

Comments
 (0)