Ejemplo n.º 1
0
    intrusive_ptr<DocumentSource> DocumentSourceProject::createFromBson(
        BSONElement *pBsonElement,
        const intrusive_ptr<ExpressionContext> &pExpCtx) {
        /* validate */
        uassert(15969, str::stream() << projectName <<
                " specification must be an object",
                pBsonElement->type() == Object);

        /* chain the projection onto the original source */
        intrusive_ptr<DocumentSourceProject> pProject(
            DocumentSourceProject::create(pExpCtx));

        /*
          Pull out the $project object.  This should just be a list of
          field inclusion or exclusion specifications.  Note you can't do
          both, except for the case of _id.
         */
        BSONObj projectObj(pBsonElement->Obj());
        BSONObjIterator fieldIterator(projectObj);
        Expression::ObjectCtx objectCtx(
            Expression::ObjectCtx::DOCUMENT_OK);
        while(fieldIterator.more()) {
            BSONElement outFieldElement(fieldIterator.next());
            string outFieldPath(outFieldElement.fieldName());
            string inFieldName(outFieldPath);
            BSONType specType = outFieldElement.type();
            int fieldInclusion = -1;

            switch(specType) {
            case NumberDouble: {
                double inclusion = outFieldElement.numberDouble();
                fieldInclusion = static_cast<int>(inclusion);
                goto IncludeExclude;
            }

            case NumberLong: {
                long long inclusion = outFieldElement.numberLong();
                fieldInclusion = static_cast<int>(inclusion);
                goto IncludeExclude;
            }

            case NumberInt:
                /* just a plain integer include/exclude specification */
                fieldInclusion = outFieldElement.numberInt();

IncludeExclude:
                uassert(15970, str::stream() <<
                        "field inclusion or exclusion specification for \"" <<
                        outFieldPath <<
                        "\" must be true, 1, false, or zero",
                        ((fieldInclusion == 0) || (fieldInclusion == 1)));

                if (fieldInclusion == 0)
                    pProject->excludePath(outFieldPath);
                else 
                    pProject->includePath(outFieldPath);
                break;

            case Bool:
                /* just a plain boolean include/exclude specification */
                fieldInclusion = (outFieldElement.Bool() ? 1 : 0);
                goto IncludeExclude;

            case String:
                /* include a field, with rename */
                fieldInclusion = 1;
                inFieldName = outFieldElement.String();
                pProject->addField(
                    outFieldPath,
                    ExpressionFieldPath::create(
                        Expression::removeFieldPrefix(inFieldName)));
                break;

            case Object: {
                intrusive_ptr<Expression> pDocument(
                    Expression::parseObject(&outFieldElement, &objectCtx));

                /* add The document expression to the projection */
                pProject->addField(outFieldPath, pDocument);
                break;
            }

            default:
                uassert(15971, str::stream() <<
                        "invalid BSON type (" << specType <<
                        ") for " << projectName <<
                        " field " << outFieldPath, false);
            }

        }

        return pProject;
    }
Ejemplo n.º 2
0
    intrusive_ptr<DocumentSource> DocumentSourceProject::createFromBson(
	BSONElement *pBsonElement,
	const intrusive_ptr<ExpressionContext> &pCtx) {
        /* validate */
        assert(pBsonElement->type() == Object); // CW TODO user error

        /* chain the projection onto the original source */
        intrusive_ptr<DocumentSourceProject> pProject(
	    DocumentSourceProject::create());

        /*
          Pull out the $project object.  This should just be a list of
          field inclusion or exclusion specifications.  Note you can't do
          both, except for the case of _id.
         */
        BSONObj projectObj(pBsonElement->Obj());
        BSONObjIterator fieldIterator(projectObj);
	Expression::ObjectCtx objectCtx(
	    Expression::ObjectCtx::DOCUMENT_OK);
        while(fieldIterator.more()) {
            BSONElement outFieldElement(fieldIterator.next());
            string outFieldPath(outFieldElement.fieldName());
            string inFieldName(outFieldPath);
            BSONType specType = outFieldElement.type();
            int fieldInclusion = -1;

            switch(specType) {
            case NumberDouble: {
                double inclusion = outFieldElement.numberDouble();
                if ((inclusion == 0) || (inclusion == 1))
                    fieldInclusion = (int)inclusion;
                else {
                    assert(false); // CW TODO unimplemented constant expression
                }

                goto IncludeExclude;
            }

            case NumberInt:
                /* just a plain integer include/exclude specification */
                fieldInclusion = outFieldElement.numberInt();
                assert((fieldInclusion >= 0) && (fieldInclusion <= 1));
                // CW TODO invalid field projection specification

IncludeExclude:
                if (fieldInclusion == 0)
		    pProject->excludePath(outFieldPath);
                else 
                    pProject->includePath(outFieldPath);
                break;

            case Bool:
                /* just a plain boolean include/exclude specification */
                fieldInclusion = outFieldElement.Bool() ? 1 : 0;
                goto IncludeExclude;

            case String:
                /* include a field, with rename */
                fieldInclusion = 1;
                inFieldName = outFieldElement.String();
		pProject->addField(
		    outFieldPath,
		    ExpressionFieldPath::create(
			Expression::removeFieldPrefix(inFieldName)));
		break;

            case Object: {
                intrusive_ptr<Expression> pDocument(
                    Expression::parseObject(&outFieldElement, &objectCtx));

                /* add The document expression to the projection */
                pProject->addField(outFieldPath, pDocument);
                break;
            }

            default:
                assert(false); // CW TODO invalid field projection specification
            }

        }

        return pProject;
    }