[SERVER-6192] $and and $or expressions may not short circuit non constants and optimize to a constant if the original expression has only one constant Created: 24/Jun/12  Updated: 11/Jul/16  Resolved: 02/Oct/13

Status: Closed
Project: Core Server
Component/s: Aggregation Framework
Affects Version/s: None
Fix Version/s: 2.5.3

Type: Improvement Priority: Major - P3
Reporter: Aaron Staple Assignee: David Storch
Resolution: Done Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related
is related to SERVER-6193 string constants prevent optimization... Closed
Participants:

 Description   

Observed behavior: A $and/$or expression with a single constant is not optimized as well as a similar expression with two constants.
Expected behavior: An expression with one constant should be optimized the same way as a similar expression with two constants.

ExpressionAnd::optimize() and ExpressionOr::optimize() expect that any constant will appear in the last operand, but ExpressionNary::optimize() does not guarantee placement of a constant in the last operand if there was only one constant to begin with.

        /*
          If there's no more than one constant, then we can't do any
          constant folding, so don't bother going any further.
         */
        if (constCount <= 1)
            return intrusive_ptr<Expression>(this);

Test:

c = db.c;
c.drop();
 
c.save( { x:true } );
 
// This expression is left as is.
printjson( c.runCommand( 'aggregate', { pipeline:[ { $project:{ a:{ $and:[ 0, '$x' ] } }\
 } ], explain:true } ) );
// This expression is optimized to 'false', eliminating the need to read field 'x', due to the existence of two constant operands.
printjson( c.runCommand( 'aggregate', { pipeline:[ { $project:{ a:{ $and:[ 0, 1, '$x' ] \
} } } ], explain:true } ) );
 
// This expression is left as is.
printjson( c.runCommand( 'aggregate', { pipeline:[ { $project:{ a:{ $or:[ 1, '$x' ] } } \
} ], explain:true } ) );
// This expression is optimized to 'true', eliminating the need to read field 'x', due to the existence of two constant operands.
printjson( c.runCommand( 'aggregate', { pipeline:[ { $project:{ a:{ $or:[ 1, 0, '$x' ] }\
 } } ], explain:true } ) );



 Comments   
Comment by auto [ 02/Oct/13 ]

Author:

{u'username': u'dannenberg', u'name': u'Matt Dannenberg', u'email': u'matt.dannenberg@10gen.com'}

Message: Merge pull request #509 from dstorch/master

SERVER-6192 SERVER-6193 js test for short-circuiting of $and and $or in $agg project phase
Branch: master
https://github.com/mongodb/mongo/commit/cc506fc6a274b57ee31dac021cdecd5aee084d08

Comment by auto [ 02/Oct/13 ]

Author:

{u'username': u'dstorch', u'name': u'David Storch', u'email': u'david.storch@10gen.com'}

Message: SERVER-6192 SERVER-6193 js test for short-circuiting of $and and $or in agg $project phase
Branch: master
https://github.com/mongodb/mongo/commit/f5168c9ae8d1e6c1bc8b09dee72dc604a75c203d

Comment by David Storch [ 01/Oct/13 ]

cr: http://codereview.10gen.com/12313003/

Comment by Mathias Stearn [ 30/Sep/13 ]

As part of QA-374, could you write a test for this case? I've manually validated that we do the right thing with these now but would like to have an automated test before closing this ticket.

Comment by Daniel Pasette (Inactive) [ 17/Sep/13 ]

redbeard0531, can you add a test for this case?

Generated at Thu Feb 08 03:11:00 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.