Пример #1
0
INT32 getIndexesCommand::convertRequest( mongoParser &parser,
                                         std::vector<msgBuffer*> &sdbMsgs )
{
   INT32 rc              = SDB_OK ;
   INT32 nToSkip         = 0 ;
   INT32 nToReturn       = 0 ;
   MsgHeader *header     = NULL ;
   MsgOpQuery *getIndex  = NULL ;
   bson::BSONObj cond ;
   bson::BSONObjBuilder obj ;
   bson::BSONObjBuilder indexObj ;
   const std::string cmdStr = "$get indexes" ;
   std::string fullname ;
   msgBuffer *sdbMsg = SDB_OSS_NEW msgBuffer() ;
   if ( NULL == sdbMsg )
   {
      rc = SDB_OOM ;
      goto error ;
   }

   parser.opType = OP_CMD_GET_INDEX ;
   sdbMsg->reverse( sizeof ( MsgOpQuery ) ) ;
   sdbMsg->advance( sizeof ( MsgOpQuery ) - 4 ) ;

   header = ( MsgHeader * )sdbMsg->data() ;
   header->opCode = MSG_BS_QUERY_REQ ;
   header->TID = 0 ;
   header->routeID.value = 0 ;
   header->requestID = parser.id ;

   getIndex = ( MsgOpQuery * )sdbMsg->data() ;
   getIndex->version = 0 ;
   getIndex->w = 0 ;
   getIndex->padding = 0 ;
   getIndex->flags = 0 ;

   getIndex->nameLength = cmdStr.length() ;
   parser.skip( parser.nsLen + 1 ) ;

   parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
   getIndex->numToSkip = 0 ;
   parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
   getIndex->numToReturn = -1 ;

   if ( parser.more() )
   {
      parser.nextObj( cond ) ;
   }

   indexObj.append( "indexDef.name", cond.getStringField( "index" ) ) ;
   obj.append( "Collection", cond.getStringField( "ns" ) ) ;

   sdbMsg->write( cmdStr.c_str(), getIndex->nameLength + 1, TRUE ) ;
   sdbMsg->write( indexObj.done(), TRUE ) ;

   sdbMsg->write( fap::emptyObj, TRUE ) ;
   sdbMsg->write( fap::emptyObj, TRUE ) ;
   sdbMsg->write( obj.done(), TRUE ) ;

   header->messageLength = sdbMsg->size() ;
   sdbMsgs.push_back( sdbMsg ) ;

done:
   return rc ;
error:
   goto done ;
}
Пример #2
0
INT32 updateCommand::convertRequest( mongoParser &parser,
                                     std::vector<msgBuffer*> &sdbMsgs )
{
   INT32 rc            = SDB_OK ;
   INT32 updateFlags   = 0 ;
   MsgHeader *header   = NULL ;
   MsgOpUpdate *update = NULL ;
   bson::BSONObj cond ;
   bson::BSONObj updater ;
   bson::BSONObj hint ;
   msgBuffer *sdbMsg = SDB_OSS_NEW msgBuffer() ;
   if ( NULL == sdbMsg )
   {
      rc = SDB_OOM ;
      goto error ;
   }

   parser.opType = OP_UPDATE ;
   sdbMsg->reverse( sizeof ( MsgOpUpdate ) ) ;
   sdbMsg->advance( sizeof ( MsgOpUpdate ) - 4 ) ;

   header = ( MsgHeader * )sdbMsg->data() ;
   header->opCode = MSG_BS_UPDATE_REQ ;
   header->TID = 0 ;
   header->routeID.value = 0 ;
   header->requestID = parser.id ;

   update = ( MsgOpUpdate * )sdbMsg->data() ;
   update->version = 0 ;
   update->w = 0 ;
   update->padding = 0 ;
   update->flags = 0 ;

   update->nameLength = parser.nsLen ;

   parser.skip( update->nameLength + 1 ) ;
   parser.readNumber( sizeof( INT32 ), (CHAR *)&updateFlags ) ;
   if ( updateFlags & UPDATE_UPSERT )
   {
      update->flags |= FLG_UPDATE_UPSERT ;
   }

   if ( updateFlags & UPDATE_MULTI )
   {
      update->flags |= FLG_UPDATE_MULTIUPDATE ;
   }

   if ( !parser.more() )
   {
      rc = SDB_INVALIDARG ;
      goto error ;
   }
   parser.nextObj( cond ) ;

   if ( !parser.more() )
   {
      rc = SDB_INVALIDARG ;
      goto error ;
   }
   parser.nextObj( updater ) ;

   hint = cond.getObjectField( "$hint" ) ;
   hint = removeField( hint, "$hint" ) ;

   sdbMsg->write( parser.fullName, update->nameLength + 1, TRUE ) ;
   sdbMsg->write( cond, TRUE ) ;
   sdbMsg->write( updater, TRUE ) ;
   sdbMsg->write( hint, TRUE ) ;

   header->messageLength = sdbMsg->size() ;
   sdbMsgs.push_back( sdbMsg ) ;

done:
   return rc ;
error:
   goto done ;
}
Пример #3
0
INT32 dropCommand::convertRequest( mongoParser &parser, msgBuffer &sdbMsg )
{
    INT32 rc          = SDB_OK ;
    INT32 nToSkip     = 0 ;
    INT32 nToReturn   = 0 ;
    MsgHeader *header = NULL ;
    MsgOpQuery *query = NULL ;
    bson::BSONObj cond ;
    bson::BSONObj obj ;
    bson::BSONElement e ;
    const std::string cmdStr = "$drop collection" ;
    std::string fullname ;

    parser.opType = OP_CMD_DROP ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    query = ( MsgOpQuery * )sdbMsg.data() ;
    query->version = 0 ;
    query->w = 0 ;
    query->padding = 0 ;
    query->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, query->flags ) ;

    fullname = parser.csName ;
    query->nameLength = cmdStr.length() ;
    parser.skip( parser.nsLen + 1 ) ;

    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
    query->numToSkip = 0 ;
    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
    query->numToReturn = (0 == nToReturn ? -1 : nToReturn) ;
    if ( 0 > nToReturn )
    {
        query->numToReturn = -nToReturn ;
    }

    if ( parser.more() )
    {
        parser.nextObj( cond ) ;
    }
    fullname += "." ;
    fullname += cond.getStringField( "drop" ) ;

    sdbMsg.write( cmdStr.c_str(), query->nameLength + 1, TRUE ) ;
    obj = BSON( "Name" << fullname.c_str() ) ;

    sdbMsg.write( obj, TRUE ) ;

    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;

    sdbMsg.doneLen() ;

    return rc ;
}
Пример #4
0
INT32 countCommand::convertRequest( mongoParser &parser, msgBuffer &sdbMsg )
{
    INT32 rc          = SDB_OK ;
    INT32 nToSkip     = 0 ;
    INT32 nToReturn   = 0 ;
    MsgHeader *header = NULL ;
    MsgOpQuery *query = NULL ;
    bson::BSONObj all ;
    bson::BSONObj queryObj ;
    bson::BSONObj orderby ;
    bson::BSONObj fields ;
    bson::BSONObj obj ;
    bson::BSONElement e ;
    const std::string cmdStr = "$get count" ;
    std::string fullname ;

    parser.opType = OP_CMD_COUNT ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    query = ( MsgOpQuery * )sdbMsg.data() ;
    query->version = 0 ;
    query->w = 0 ;
    query->padding = 0 ;
    query->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, query->flags ) ;

    fullname = parser.csName ;

    query->nameLength = cmdStr.length() ;
    parser.skip( parser.nsLen + 1 ) ;

    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
    query->numToSkip = nToSkip ;
    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
    query->numToReturn = nToReturn ;

    if ( parser.more() )
    {
        parser.nextObj( all ) ;
    }

    fullname += "." ;
    fullname += all.getStringField( "count" ) ;

    query->nameLength = cmdStr.length() ;
    sdbMsg.write( cmdStr.c_str(), query->nameLength + 1, TRUE ) ;
    obj = BSON( "Collection" << fullname.c_str() ) ;

    queryObj = fap::getCondObj( all ) ;
    orderby = all.getObjectField( "sort" ) ;
    if ( all.hasField( "limit" ) )
    {
        query->numToReturn = all.getIntField( "limit" ) ;
    }

    if ( all.hasField( "skip" ) )
    {
        query->numToSkip = all.getIntField( "skip" ) ;
    }

    sdbMsg.write( queryObj, TRUE ) ;
    sdbMsg.write( fields, TRUE ) ;
    sdbMsg.write( orderby, TRUE ) ;
    sdbMsg.write( obj, TRUE ) ;

    sdbMsg.doneLen() ;

    return rc ;
}
Пример #5
0
INT32 queryCommand::convertRequest( mongoParser &parser, msgBuffer &sdbMsg )
{
    INT32 rc           = SDB_OK ;
    INT32 nToSkip      = 0 ;
    INT32 nToReturn    = -1 ;
    MsgHeader *header  = NULL ;
    MsgOpQuery *query  = NULL ;
    const CHAR *cmdStr = NULL ;
    command* cmd       = NULL ;
    bson::BSONObj all ;
    bson::BSONObj cond ;
    bson::BSONObj selector ;
    bson::BSONObj orderby ;
    bson::BSONObj hint ;
    bson::BSONObj fieldToReturn ;

    parser.opType = OP_QUERY ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    query = ( MsgOpQuery * )sdbMsg.data() ;
    query->version = 0 ;
    query->w = 0 ;
    query->padding = 0 ;
    query->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, query->flags ) ;

    query->nameLength = parser.nsLen ;
    parser.skip( query->nameLength + 1 ) ;

    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
    query->numToSkip = nToSkip ;
    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
    query->numToReturn = (0 == nToReturn ? -1 : nToReturn) ;
    if ( 0 > nToReturn )
    {
        query->numToReturn = -nToReturn ;
    }

    if ( parser.more() )
    {
        parser.nextObj( all ) ;
    }

    if ( parser.withIndex )
    {
        cmd = commandMgr::instance()->findCommand( "listIndexes" ) ;
        if ( NULL == cmd )
        {
            rc = SDB_OPTION_NOT_SUPPORT ;
            parser.opType = OP_CMD_NOT_SUPPORTED ;
            goto error ;
        }
        parser.reparse() ;
        sdbMsg.zero() ;

        rc = cmd->convertRequest( parser, sdbMsg ) ;
        goto done ;
    }

    if ( parser.withCmd )
    {
        cmdStr = all.firstElementFieldName() ;
        cmd = commandMgr::instance()->findCommand( cmdStr ) ;
        if ( NULL == cmd )
        {
            rc = SDB_OPTION_NOT_SUPPORT ;
            parser.opType = OP_CMD_NOT_SUPPORTED ;
            parser.cmdName = cmdStr ;
            goto error ;
        }
        parser.reparse() ;
        sdbMsg.zero() ;

        rc = cmd->convertRequest( parser, sdbMsg ) ;
        goto done ;
    }

    cond = fap::getCondObj( all ) ;
    orderby = all.getObjectField( "orderby" ) ;
    hint    = cond.getObjectField( "$hint" ) ;

    if ( all.hasField( "limit" ) )
    {
        query->numToReturn = cond.getIntField( "limit" ) ;
    }

    if ( all.hasField( "skip" ) )
    {
        query->numToSkip   = cond.getIntField( "skip" ) ;
    }

    if ( cond.getBoolField("$explain") )
    {
        query->flags |= FLG_QUERY_EXPLAIN ;
    }

    if ( parser.more() )
    {
        parser.nextObj( fieldToReturn ) ;
    }

    sdbMsg.write( parser.fullName, query->nameLength + 1, TRUE ) ;
    sdbMsg.write( cond, TRUE ) ;
    sdbMsg.write( fieldToReturn, TRUE ) ;
    sdbMsg.write( orderby, TRUE ) ;
    sdbMsg.write( hint, TRUE ) ;

    sdbMsg.doneLen() ;

done:
    return rc ;
error:
    goto done ;
}
Пример #6
0
INT32 updateCommand::convertRequest( mongoParser &parser, msgBuffer &sdbMsg )
{
    INT32 rc            = SDB_OK ;
    INT32 nToSkip       = 0 ;
    INT32 nToReturned   = 0 ;
    INT32 updateFlags   = 0 ;
    MsgHeader *header   = NULL ;
    MsgOpUpdate *update = NULL ;
    bson::BSONObj all ;
    bson::BSONObj cond ;
    bson::BSONObj updator ;
    bson::BSONObj hint ;

    std::string fullname ;
    bson::BSONObj obj ;
    bson::BSONObj subObj ;
    bson::BSONElement e ;
    std::vector< bson::BSONElement > objList ;
    std::vector< bson::BSONElement >::const_iterator cit ;

    parser.opType = OP_UPDATE ;
    sdbMsg.reverse( sizeof ( MsgOpUpdate ) ) ;
    sdbMsg.advance( sizeof ( MsgOpUpdate ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_UPDATE_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    update = ( MsgOpUpdate * )sdbMsg.data() ;
    update->version = 0 ;
    update->w = 0 ;
    update->padding = 0 ;
    update->flags = 0 ;

    parser.skip( parser.nsLen + 1 ) ;
    if ( parser.withCmd )
    {
        parser.skip( sizeof( nToSkip ) + sizeof( nToReturned ) ) ;
        if ( !parser.more() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }

        parser.nextObj( obj ) ;
        fullname += parser.csName ;
        fullname += "." ;
        fullname += obj.getStringField( "update" ) ;
        sdbMsg.write( fullname.c_str() , fullname.length() + 1, TRUE ) ;
        update->nameLength = fullname.length() ;
        e = obj.getField( "updates" ) ;
        if ( bson::Array != e.type() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }
        objList = e.Array() ;
        cit = objList.begin() ;
        while ( objList.end() != cit )
        {
            subObj = (*cit).Obj() ;
            all= subObj.getObjectField( "q" ) ;// u , multi upsert

            cond = fap::getCondObj( all ) ;

            updator = subObj.getObjectField( "u" ) ;

            hint = all.getObjectField( "$hint" ) ;
            BOOLEAN tmp = 0 ;
            tmp = subObj.getBoolField( "multi" ) ;
            if ( tmp )
            {
                update->flags |= FLG_UPDATE_MULTIUPDATE ;
            }
            tmp = subObj.getBoolField( "upsert" ) ;
            if ( tmp )
            {
                update->flags |= FLG_UPDATE_UPSERT ;
            }
            sdbMsg.write( cond, TRUE ) ;
            sdbMsg.write( updator, TRUE ) ;
            sdbMsg.write( hint, TRUE ) ;
            ++cit ;
        }
    }
    else
    {
        update->nameLength = parser.nsLen ;
        parser.readNumber( sizeof( INT32 ), (CHAR *)&updateFlags ) ;
        if ( updateFlags & UPDATE_UPSERT )
        {
            update->flags |= FLG_UPDATE_UPSERT ;
        }

        if ( updateFlags & UPDATE_MULTI )
        {
            update->flags |= FLG_UPDATE_MULTIUPDATE ;
        }

        if ( !parser.more() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }
        parser.nextObj( all ) ;

        if ( !parser.more() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }
        parser.nextObj( updator ) ;

        cond = fap::getCondObj( all ) ;
        hint = all.getObjectField( "$hint" ) ;

        sdbMsg.write( parser.fullName, update->nameLength + 1, TRUE ) ;
        sdbMsg.write( cond, TRUE ) ;
        sdbMsg.write( updator, TRUE ) ;
        sdbMsg.write( hint, TRUE ) ;
    }

    sdbMsg.doneLen() ;

done:
    return rc ;
error:
    goto done ;
}
Пример #7
0
INT32 listIndexesCommand::convertRequest( mongoParser &parser,
        msgBuffer &sdbMsg )
{
    INT32 rc              = SDB_OK ;
    INT32 nToSkip         = 0 ;
    INT32 nToReturn       = 0 ;
    MsgHeader *header     = NULL ;
    MsgOpQuery *getIndex  = NULL ;
    bson::BSONObj cond ;
    bson::BSONObj indexObj ;
    bson::BSONObjBuilder obj ;
    const std::string cmdStr = "$get indexes" ;
    std::string fullname ;

    parser.opType = OP_CMD_GET_INDEX ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    getIndex = ( MsgOpQuery * )sdbMsg.data() ;
    getIndex->version = 0 ;
    getIndex->w = 0 ;
    getIndex->padding = 0 ;
    getIndex->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, getIndex->flags ) ;

    getIndex->nameLength = cmdStr.length() ;
    parser.skip( parser.nsLen + 1 ) ;

    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
    getIndex->numToSkip = 0 ;
    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
    getIndex->numToReturn = (0 == nToReturn ? -1 : nToReturn) ;
    if ( 0 > nToReturn )
    {
        getIndex->numToReturn = -nToReturn ;
    }

    if ( parser.more() )
    {
        parser.nextObj( cond ) ;
    }

    if ( parser.withIndex )
    {
        if ( cond.hasField( "index" ) )
        {
            indexObj = BSON( "indexDef.name" << cond.getStringField( "index" )  ) ;
        }
        obj.append( "Collection", cond.getStringField( "ns" ) ) ;
    }
    else if ( parser.withCmd )
    {
        parser.opType = OP_CMD_NOT_SUPPORTED ;
        parser.cmdName = cond.firstElementFieldName() ;

        fullname = parser.csName ;
        fullname += "." ;
        fullname += cond.getStringField( "listIndexes" ) ;
        obj.append( "Collection", fullname.c_str() ) ;
    }

    sdbMsg.write( cmdStr.c_str(), getIndex->nameLength + 1, TRUE ) ;
    sdbMsg.write( indexObj, TRUE ) ;

    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( obj.obj(), TRUE ) ;

    sdbMsg.doneLen() ;

    return rc ;
}
Пример #8
0
INT32 deleteIndexesCommand::convertRequest( mongoParser &parser,
        msgBuffer &sdbMsg )
{
    INT32 rc              = SDB_OK ;
    INT32 nToSkip         = 0 ;
    INT32 nToReturn       = 0 ;
    MsgHeader *header     = NULL ;
    MsgOpQuery *dropIndex = NULL ;
    bson::BSONObj cond ;
    bson::BSONObj obj ;
    bson::BSONObjBuilder indexObj ;
    bson::BSONElement e ;
    const std::string cmdStr = "$drop index" ;
    std::string fullname ;

    parser.opType = OP_CMD_DROP_INDEX ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    dropIndex = ( MsgOpQuery * )sdbMsg.data() ;
    dropIndex->version = 0 ;
    dropIndex->w = 0 ;
    dropIndex->padding = 0 ;
    dropIndex->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, dropIndex->flags ) ;

    fullname = parser.csName ;
    dropIndex->nameLength = cmdStr.length() ;
    parser.skip( parser.nsLen + 1 ) ;

    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
    dropIndex->numToSkip = 0 ;
    parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
    dropIndex->numToReturn = (0 == nToReturn ? -1 : nToReturn) ;
    if ( 0 > nToReturn )
    {
        dropIndex->numToReturn = -nToReturn ;
    }

    if ( parser.more() )
    {
        parser.nextObj( cond ) ;
    }

    {
        std::string clname = cond.getStringField( "deleteIndexes" ) ;
        if ( clname.empty() )
        {
            clname = cond.getStringField( "dropIndexes" ) ;
            if ( clname.empty() )
            {
                rc = SDB_INVALIDARG ;
                goto error ;
            }
        }
        fullname += "." ;
        fullname += clname ;
    }

    indexObj.append( "", cond.getStringField( "index" ) ) ;
    obj = BSON( "Collection" << fullname.c_str() << "Index" << indexObj.obj() );

    sdbMsg.write( cmdStr.c_str(), dropIndex->nameLength + 1, TRUE ) ;
    sdbMsg.write( obj, TRUE ) ;

    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;

    sdbMsg.doneLen() ;

done:
    return rc ;
error:
    goto done ;
}
Пример #9
0
INT32 createIndexesCommand::convertRequest( mongoParser &parser,
        msgBuffer &sdbMsg )
{
    INT32 rc           = SDB_OK ;
    INT32 nToSkip      = 0 ;
    INT32 nToReturn    = 0 ;
    MsgHeader *header  = NULL ;
    MsgOpQuery *index  = NULL ;
    bson::BSONObj cond ;
    bson::BSONObj subObj ;
    bson::BSONElement e ;
    std::vector< bson::BSONElement > objList ;
    std::vector< bson::BSONElement >::const_iterator cit ;
    bson::BSONObjBuilder obj ;
    bson::BSONObjBuilder indexobj ;
    const std::string cmdStr = "$create index" ;
    std::string fullname ;

    parser.opType = OP_ENSURE_INDEX ;
    sdbMsg.reverse( sizeof ( MsgOpQuery ) ) ;
    sdbMsg.advance( sizeof ( MsgOpQuery ) - 4 ) ;

    header = ( MsgHeader * )sdbMsg.data() ;
    header->opCode = MSG_BS_QUERY_REQ ;
    header->TID = 0 ;
    header->routeID.value = 0 ;
    header->requestID = parser.id ;

    index = ( MsgOpQuery * )sdbMsg.data() ;
    index->version = 0 ;
    index->w = 0 ;
    index->padding = 0 ;
    index->flags = 0 ;
    fap::setQueryFlags( parser.reservedFlags, index->flags ) ;

    fullname = parser.csName ;
    parser.skip( parser.nsLen + 1 ) ;

    if ( parser.withCmd )
    {
        parser.skip( sizeof( nToSkip ) + sizeof( nToReturn ) ) ;
        index->numToSkip = 0 ;
        index->numToReturn = nToReturn <= 0 ? -1 : nToReturn ;
        if ( !parser.more() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }//createIndexes

        parser.nextObj( cond ) ;

        index->nameLength = cmdStr.length() ;
        sdbMsg.write( cmdStr.c_str(), index->nameLength + 1, TRUE ) ;
        fullname += "." ;
        fullname += cond.getStringField( "createIndexes" ) ;
        obj.append( "Collection", fullname.c_str() ) ;
        e = cond.getField( "indexes" ) ;
        if ( bson::Array != e.type() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }
        objList = e.Array() ;
        cit = objList.begin() ;
        while ( objList.end() != cit )
        {
            subObj = (*cit).Obj() ;
            indexobj.append( "key", subObj.getObjectField( "key" ) ) ;
            indexobj.append( "name", subObj.getStringField( "name" ) ) ;
            indexobj.append("unique", subObj.getBoolField( "unique" ) ) ;
            obj.append( "Index", indexobj.obj() ) ;
            sdbMsg.write( obj.obj(), TRUE ) ;
            ++cit ;
        }
    }
    else
    {
        parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToSkip ) ;
        index->numToSkip = 0 ;
        parser.readNumber( sizeof( INT32 ), ( CHAR * )&nToReturn ) ;
        index->numToReturn = (0 == nToReturn ? -1 : nToReturn) ;
        if ( 0 > nToReturn )
        {
            index->numToReturn = -nToReturn ;
        }
        index->nameLength = cmdStr.length() ;
        sdbMsg.write( cmdStr.c_str(), index->nameLength + 1, TRUE ) ;

        if ( !parser.more() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }

        parser.nextObj( cond ) ;
        e = cond.getField( "documents" ) ;
        if ( bson::Array != e.type() )
        {
            rc = SDB_INVALIDARG ;
            goto error ;
        }
        objList = e.Array() ;
        cit = objList.begin() ;
        while ( objList.end() != cit )
        {
            subObj = (*cit).Obj() ;
            obj.append( "Collection", subObj.getStringField( "ns" ) ) ;
            indexobj.append( "key", subObj.getObjectField( "key" ) ) ;
            indexobj.append( "name", subObj.getStringField( "name" ) ) ;
            indexobj.append("unique", subObj.getBoolField( "unique" ) ) ;
            obj.append( "Index", indexobj.obj() ) ;
            sdbMsg.write( obj.obj(), TRUE ) ;
            ++cit ;
        }
    }
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.write( fap::emptyObj, TRUE ) ;
    sdbMsg.doneLen() ;

done:
    return rc ;
error:
    goto done ;
}