@@ -1978,62 +1978,85 @@ namespace mongo {
19781978 list<BSONObj> DBClientWithCommands::getIndexSpecs ( const string &ns, int options ) {
19791979 list<BSONObj> specs;
19801980
1981- {
1982- // TODO: This implementation only reads the first batch of results from the
1983- // listIndexes command, and masserts if there are multiple batches to read. A
1984- // correct implementation needs to instantiate a command cursor from the command
1985- // response object, and use it to read in all of the command results.
1986- BSONObj cmd = BSON (
1987- " listIndexes" << nsToCollectionSubstring ( ns ) <<
1988- " cursor" << BSONObj ()
1989- );
1990-
1991- BSONObj res;
1992- if ( runCommand ( nsToDatabase ( ns ), cmd, res, options ) ) {
1993- BSONObj cursorObj = res[" cursor" ].Obj ();
1994- massert (28587 , " reading multiple batches from listIndexes not implemented" ,
1995- cursorObj[" id" ].numberInt () == 0 );
1996- BSONObjIterator i ( cursorObj[" firstBatch" ].Obj () );
1997- while ( i.more () ) {
1998- specs.push_back ( i.next ().Obj ().getOwned () );
1999- }
2000- return specs;
2001- }
2002- int code = res[" code" ].numberInt ();
2003- string errmsg = res[" errmsg" ].valuestrsafe ();
2004- if ( code == ErrorCodes::CommandNotFound ||
2005- errmsg.find ( " no such cmd" ) != string::npos ) {
2006- // old version of server, ok, fall through to old code
2007- }
2008- else if ( code == ErrorCodes::NamespaceNotFound ) {
2009- return specs;
2010- }
2011- else {
2012- uasserted ( 18631 , str::stream () << " listIndexes failed: " << res );
1981+ auto_ptr<DBClientCursor> specs_cursor = enumerateIndexes (ns, options);
1982+
1983+ if ( specs_cursor.get () ) {
1984+ while ( specs_cursor->more () ) {
1985+ specs.push_back (specs_cursor->nextSafe ().getOwned ());
20131986 }
20141987 }
20151988
2016- // fallback to querying system.indexes
2017- // TODO(spencer): Remove fallback behavior after 2.8
2018- auto_ptr<DBClientCursor> cursor = query (NamespaceString (ns).getSystemIndexesCollection (),
2019- BSON (" ns" << ns), 0 , 0 , 0 , options);
2020- while ( cursor->more () ) {
2021- BSONObj spec = cursor->nextSafe ();
2022- specs.push_back ( spec.getOwned () );
2023- }
20241989 return specs;
20251990 }
20261991
2027- list<std::string> DBClientWithCommands::getIndexNames ( const std::string& ns ) {
1992+ list<std::string> DBClientWithCommands::getIndexNames ( const std::string& ns, int options ) {
20281993 list<std::string> indexNames;
2029- list<BSONObj> specs ( getIndexSpecs (ns) );
20301994
2031- for (list<BSONObj>::const_iterator it = specs.begin (); it != specs.end (); ++it) {
2032- indexNames.push_back ((*it)[" name" ].valuestr ());
1995+ auto_ptr<DBClientCursor> specs_cursor = enumerateIndexes (ns, options);
1996+
1997+ if ( specs_cursor.get () ) {
1998+ while ( specs_cursor->more () ) {
1999+ indexNames.push_back (specs_cursor->nextSafe ()[" name" ].valuestr ());
2000+ }
20332001 }
2002+
20342003 return indexNames;
20352004 }
20362005
2006+ auto_ptr<DBClientCursor> DBClientWithCommands::enumerateIndexes ( const string& ns, int options ) {
2007+ const NamespaceString nsstring (ns);
2008+
2009+ BSONObj cmd = BSON (" listIndexes" << nsstring.coll () << " cursor" << BSONObj ());
2010+
2011+ auto_ptr<DBClientCursor> cursor = this ->query (nsstring.getCommandNS (), cmd, 1 , 0 , NULL ,
2012+ options, 0 );
2013+ BSONObj result = cursor->peekFirst ();
2014+
2015+ if ( isOk (result) ) {
2016+ // Command worked -- we are on MongoDB 2.7.6 or above
2017+ DBClientCursorShim* cursor_shim;
2018+
2019+ // Select the appropriate shim for this version of MongoDB
2020+ if ( result.hasField (" indexes" ) ) {
2021+ // MongoDB 2.7.6 to 2.8.0-rc2 behavior
2022+ cursor_shim = new DBClientCursorShimArray (*cursor, " indexes" );
2023+ }
2024+ else {
2025+ // MongoDB 2.8.0-rc3+ behavior
2026+ cursor_shim = new DBClientCursorShimCursorID (*cursor);
2027+ static_cast <DBClientCursorShimCursorID*>(cursor_shim)->get_cursor ();
2028+ }
2029+
2030+ // Insert the shim
2031+ cursor->shim .reset (cursor_shim);
2032+ }
2033+ else {
2034+ // Command failed -- we are either on an older MongoDB or something else happened
2035+ int error_code = result[" code" ].numberInt ();
2036+ string errmsg = result[" errmsg" ].valuestrsafe ();
2037+
2038+ if ( error_code == ErrorCodes::NamespaceNotFound ) {
2039+ cursor.reset (NULL );
2040+ }
2041+ else if (
2042+ ( error_code == ErrorCodes::CommandNotFound ) ||
2043+ ( error_code == 13390 ) ||
2044+ ( errmsg.find ( " no such cmd" ) != string::npos )
2045+ ) {
2046+ // MongoDB < 2.7.6 behavior -- query system.indexes
2047+ cursor.reset (query (nsstring.getSystemIndexesCollection (), BSON (" ns" << ns),
2048+ 0 , 0 , 0 , options).release ());
2049+ }
2050+ else {
2051+ // Something else happened, uassert with the reason
2052+ uasserted ( 18631 , str::stream () << " listIndexes failed: " << result );
2053+ }
2054+ }
2055+
2056+ return cursor;
2057+ }
2058+
2059+
20372060 void DBClientWithCommands::dropIndex ( const string& ns , BSONObj keys ) {
20382061 dropIndex ( ns , genIndexName ( keys ) );
20392062 }
0 commit comments