summaryrefslogtreecommitdiff
path: root/src/mongo/client/dbclient.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/mongo/client/dbclient.cpp')
-rw-r--r--src/mongo/client/dbclient.cpp89
1 files changed, 78 insertions, 11 deletions
diff --git a/src/mongo/client/dbclient.cpp b/src/mongo/client/dbclient.cpp
index 4c114078d7c..d45ce2c8389 100644
--- a/src/mongo/client/dbclient.cpp
+++ b/src/mongo/client/dbclient.cpp
@@ -850,28 +850,95 @@ namespace mongo {
return names;
}
-
list<string> DBClientWithCommands::getCollectionNames( const string& db ) {
+ list<BSONObj> infos = getCollectionInfos( db );
list<string> names;
+ for ( list<BSONObj>::iterator it = infos.begin(); it != infos.end(); ++it ) {
+ names.push_back( db + "." + (*it)["name"].valuestr() );
+ }
+ return names;
+ }
+
+ list<BSONObj> DBClientWithCommands::getCollectionInfos( const string& db,
+ const BSONObj& filter ) {
+ list<BSONObj> infos;
+
+ // first we're going to try the command
+ // it was only added in 3.0, so if we're talking to an older server
+ // we'll fail back to querying system.namespaces
+ // TODO(spencer): remove fallback behavior after 3.0
+
+ {
+ BSONObj res;
+ if (runCommand(db,
+ BSON("listCollections" << 1 << "filter" << filter
+ << "cursor" << BSONObj()),
+ res,
+ QueryOption_SlaveOk)) {
+ BSONObj cursorObj = res["cursor"].Obj();
+ BSONObj collections = cursorObj["firstBatch"].Obj();
+ BSONObjIterator it( collections );
+ while ( it.more() ) {
+ BSONElement e = it.next();
+ infos.push_back( e.Obj().getOwned() );
+ }
+
+ const long long id = cursorObj["id"].Long();
+
+ if ( id != 0 ) {
+ const std::string ns = cursorObj["ns"].String();
+ auto_ptr<DBClientCursor> cursor = getMore(ns, id, 0, 0);
+ while ( cursor->more() ) {
+ infos.push_back(cursor->nextSafe().getOwned());
+ }
+ }
+
+ return infos;
+ }
+
+ // command failed
+
+ int code = res["code"].numberInt();
+ string errmsg = res["errmsg"].valuestrsafe();
+ if ( code == ErrorCodes::CommandNotFound ||
+ errmsg.find( "no such cmd" ) != string::npos ) {
+ // old version of server, ok, fall through to old code
+ }
+ else {
+ uasserted( 18630, str::stream() << "listCollections failed: " << res );
+ }
+
+ }
+
+ // SERVER-14951 filter for old version fallback needs to db qualify the 'name' element
+ BSONObjBuilder fallbackFilter;
+ if ( filter.hasField( "name" ) && filter["name"].type() == String ) {
+ fallbackFilter.append( "name", db + "." + filter["name"].str() );
+ }
+ fallbackFilter.appendElementsUnique( filter );
string ns = db + ".system.namespaces";
- auto_ptr<DBClientCursor> c = query( ns.c_str() , BSONObj() );
+ auto_ptr<DBClientCursor> c = query(
+ ns.c_str(), fallbackFilter.obj(), 0, 0, 0, QueryOption_SlaveOk);
while ( c->more() ) {
- string name = c->nextSafe()["name"].valuestr();
- if ( name.find( "$" ) != string::npos )
+ BSONObj obj = c->nextSafe();
+ string ns = obj["name"].valuestr();
+ if ( ns.find( "$" ) != string::npos )
continue;
- names.push_back( name );
+ BSONObjBuilder b;
+ b.append( "name", ns.substr( db.size() + 1 ) );
+ b.appendElementsUnique( obj );
+ infos.push_back( b.obj() );
}
- return names;
+
+ return infos;
}
bool DBClientWithCommands::exists( const string& ns ) {
-
- string db = nsGetDB( ns ) + ".system.namespaces";
- BSONObj q = BSON( "name" << ns );
- return count( db.c_str() , q, QueryOption_SlaveOk ) != 0;
+ BSONObj filter = BSON( "name" << nsToCollectionSubstring( ns ) );
+ list<BSONObj> results = getCollectionInfos( nsToDatabase( ns ), filter );
+ return !results.empty();
}
-
/* --- dbclientconnection --- */
void DBClientConnection::_auth(const BSONObj& params) {