Exemplo n.º 1
0
 void run() {
     dblock lk;
     const char *ns = "unittests.cursortests.BtreeCursorTests.MultiRangeGap";
     {
         DBDirectClient c;
         for( int i = 0; i < 10; ++i )
             c.insert( ns, BSON( "a" << i ) );
         for( int i = 100; i < 110; ++i )
             c.insert( ns, BSON( "a" << i ) );
         ASSERT( c.ensureIndex( ns, BSON( "a" << 1 ) ) );
     }
     BoundList b;
     b.push_back( pair< BSONObj, BSONObj >( BSON( "" << -50 ), BSON( "" << 2 ) ) );
     b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 40 ), BSON( "" << 60 ) ) );
     b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 109 ), BSON( "" << 200 ) ) );
     Client::Context ctx( ns );
     BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->idx(1), b, 1 );
     ASSERT_EQUALS( "BtreeCursor a_1 multi", c.toString() );
     double expected[] = { 0, 1, 2, 109 };
     for( int i = 0; i < 4; ++i ) {
         ASSERT( c.ok() );
         ASSERT_EQUALS( expected[ i ], c.currKey().firstElement().number() );
         c.advance();
     }
     ASSERT( !c.ok() );
 }
Exemplo n.º 2
0
 void run() {
     dblock lk;
     const char *ns = "unittests.cursortests.BtreeCursorTests.MultiRangeReverse";
     {
         DBDirectClient c;
         for( int i = 0; i < 10; ++i )
             c.insert( ns, BSON( "a" << i ) );
         ASSERT( c.ensureIndex( ns, BSON( "a" << 1 ) ) );
     }
     BoundList b;
     b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 6 ), BSON( "" << 4 ) ) );
     b.push_back( pair< BSONObj, BSONObj >( BSON( "" << 2 ), BSON( "" << 1 ) ) );
     setClient( ns );
     BtreeCursor c( nsdetails( ns ), 1, nsdetails( ns )->indexes[ 1 ], b, -1 );
     ASSERT_EQUALS( "BtreeCursor a_1 reverse multi", c.toString() );
     double expected[] = { 6, 5, 4, 2, 1 };
     for( int i = 0; i < 5; ++i ) {
         ASSERT( c.ok() );
         ASSERT_EQUALS( expected[ i ], c.currKey().firstElement().number() );
         c.advance();
     }
     ASSERT( !c.ok() );
 }
Exemplo n.º 3
0
BoundList ShardKeyPattern::flattenBounds(const IndexBounds& indexBounds) const {
    invariant(indexBounds.fields.size() == (size_t)_keyPattern.toBSON().nFields());

    // If any field is unsatisfied, return empty bound list.
    for (vector<OrderedIntervalList>::const_iterator it = indexBounds.fields.begin();
         it != indexBounds.fields.end();
         it++) {
        if (it->intervals.size() == 0) {
            return BoundList();
        }
    }
    // To construct our bounds we will generate intervals based on bounds for
    // the first field, then compound intervals based on constraints for the first
    // 2 fields, then compound intervals for the first 3 fields, etc.
    // As we loop through the fields, we start generating new intervals that will later
    // get extended in another iteration of the loop.  We define these partially constructed
    // intervals using pairs of BSONObjBuilders (shared_ptrs, since after one iteration of the
    // loop they still must exist outside their scope).
    typedef vector<pair<shared_ptr<BSONObjBuilder>, shared_ptr<BSONObjBuilder>>> BoundBuilders;

    BoundBuilders builders;
    builders.push_back(make_pair(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()),
                                 shared_ptr<BSONObjBuilder>(new BSONObjBuilder())));
    BSONObjIterator keyIter(_keyPattern.toBSON());
    // until equalityOnly is false, we are just dealing with equality (no range or $in queries).
    bool equalityOnly = true;

    for (size_t i = 0; i < indexBounds.fields.size(); i++) {
        BSONElement e = keyIter.next();

        StringData fieldName = e.fieldNameStringData();

        // get the relevant intervals for this field, but we may have to transform the
        // list of what's relevant according to the expression for this field
        const OrderedIntervalList& oil = indexBounds.fields[i];
        const vector<Interval>& intervals = oil.intervals;

        if (equalityOnly) {
            if (intervals.size() == 1 && intervals.front().isPoint()) {
                // this field is only a single point-interval
                BoundBuilders::const_iterator j;
                for (j = builders.begin(); j != builders.end(); ++j) {
                    j->first->appendAs(intervals.front().start, fieldName);
                    j->second->appendAs(intervals.front().end, fieldName);
                }
            } else {
                // This clause is the first to generate more than a single point.
                // We only execute this clause once. After that, we simplify the bound
                // extensions to prevent combinatorial explosion.
                equalityOnly = false;

                BoundBuilders newBuilders;

                for (BoundBuilders::const_iterator it = builders.begin(); it != builders.end();
                     ++it) {
                    BSONObj first = it->first->obj();
                    BSONObj second = it->second->obj();

                    for (vector<Interval>::const_iterator interval = intervals.begin();
                         interval != intervals.end();
                         ++interval) {
                        uassert(17439,
                                "combinatorial limit of $in partitioning of results exceeded",
                                newBuilders.size() < kMaxFlattenedInCombinations);
                        newBuilders.push_back(  //
                            make_pair(shared_ptr<BSONObjBuilder>(new BSONObjBuilder()),
                                      shared_ptr<BSONObjBuilder>(new BSONObjBuilder())));
                        newBuilders.back().first->appendElements(first);
                        newBuilders.back().second->appendElements(second);
                        newBuilders.back().first->appendAs(interval->start, fieldName);
                        newBuilders.back().second->appendAs(interval->end, fieldName);
                    }
                }
                builders = newBuilders;
            }
        } else {
            // if we've already generated a range or multiple point-intervals
            // just extend what we've generated with min/max bounds for this field
            BoundBuilders::const_iterator j;
            for (j = builders.begin(); j != builders.end(); ++j) {
                j->first->appendAs(intervals.front().start, fieldName);
                j->second->appendAs(intervals.back().end, fieldName);
            }
        }
    }
    BoundList ret;
    for (BoundBuilders::const_iterator i = builders.begin(); i != builders.end(); ++i)
        ret.push_back(make_pair(i->first->obj(), i->second->obj()));
    return ret;
}