1// Copyright (C) MongoDB, Inc. 2017-present. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); you may 4// not use this file except in compliance with the License. You may obtain 5// a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7package mongo 8 9import ( 10 "context" 11 "errors" 12 13 "go.mongodb.org/mongo-driver/bson" 14 "go.mongodb.org/mongo-driver/bson/bsoncodec" 15) 16 17// ErrNoDocuments is returned by SingleResult methods when the operation that created the SingleResult did not return 18// any documents. 19var ErrNoDocuments = errors.New("mongo: no documents in result") 20 21// SingleResult represents a single document returned from an operation. If the operation resulted in an error, all 22// SingleResult methods will return that error. If the operation did not return any documents, all SingleResult methods 23// will return ErrNoDocuments. 24type SingleResult struct { 25 err error 26 cur *Cursor 27 rdr bson.Raw 28 reg *bsoncodec.Registry 29} 30 31// Decode will unmarshal the document represented by this SingleResult into v. If there was an error from the operation 32// that created this SingleResult, that error will be returned. If the operation returned no documents, DecodeBytes will 33// return ErrNoDocuments. 34// 35// If the operation was successful and returned a document, Decode will return any errors from the unmarshalling process 36// without any modification. If v is nil or is a typed nil, an error will be returned. 37func (sr *SingleResult) Decode(v interface{}) error { 38 if sr.err != nil { 39 return sr.err 40 } 41 if sr.reg == nil { 42 return bson.ErrNilRegistry 43 } 44 45 if sr.err = sr.setRdrContents(); sr.err != nil { 46 return sr.err 47 } 48 return bson.UnmarshalWithRegistry(sr.reg, sr.rdr, v) 49} 50 51// DecodeBytes will return the document represented by this SingleResult as a bson.Raw. If there was an error from the 52// operation that created this SingleResult, both the result and that error will be returned. If the operation returned 53// no documents, this will return (nil, ErrNoDocuments). 54func (sr *SingleResult) DecodeBytes() (bson.Raw, error) { 55 if sr.err != nil { 56 return sr.rdr, sr.err 57 } 58 59 if sr.err = sr.setRdrContents(); sr.err != nil { 60 return nil, sr.err 61 } 62 return sr.rdr, nil 63} 64 65// setRdrContents will set the contents of rdr by iterating the underlying cursor if necessary. 66func (sr *SingleResult) setRdrContents() error { 67 switch { 68 case sr.err != nil: 69 return sr.err 70 case sr.rdr != nil: 71 return nil 72 case sr.cur != nil: 73 defer sr.cur.Close(context.TODO()) 74 if !sr.cur.Next(context.TODO()) { 75 if err := sr.cur.Err(); err != nil { 76 return err 77 } 78 79 return ErrNoDocuments 80 } 81 sr.rdr = sr.cur.Current 82 return nil 83 } 84 85 return ErrNoDocuments 86} 87 88// Err returns the error from the operation that created this SingleResult. If the operation was successful but did not 89// return any documents, Err will return ErrNoDocuments. If the operation was successful and returned a document, Err 90// will return nil. 91func (sr *SingleResult) Err() error { 92 sr.err = sr.setRdrContents() 93 94 return sr.err 95} 96