Compare commits

...

1 Commits

Author SHA1 Message Date
Nicholas Zolnierz
76d67ea903 SERVER-62322 Allow an empty object to be projected in $setWindowFields 2022-01-19 15:21:36 -05:00
2 changed files with 16 additions and 4 deletions

View File

@@ -213,8 +213,7 @@ assert.commandWorked(run({
}));
// Not every accumulator is automatically a window function.
var err = assert.commandFailedWithCode(run({$setWindowFields: {output: {a: {b: {$sum: "$a"}}}}}),
let err = assert.commandFailedWithCode(run({$setWindowFields: {output: {a: {b: {$sum: "$a"}}}}}),
ErrorCodes.FailedToParse);
assert.includes(err.errmsg, 'Expected a $-prefixed window function, b');
@@ -250,4 +249,14 @@ err = assert.commandFailedWithCode(
}),
ErrorCodes.FailedToParse);
assert.includes(err.errmsg, 'Unrecognized window function, $summ');
// Test that an empty object is a valid projected field.
assert.commandWorked(coll.insert({}));
assert.commandWorked(run({$setWindowFields: {output: {v: {$max: {mergeObjects: {}}}}}}));
// However conflicting field paths is always an error.
err = assert.commandFailedWithCode(
run({$setWindowFields: {output: {a: {$sum: 1}, 'a.b': {$sum: 1}}}}), 40176);
assert.includes(err.errmsg, 'specification contains two conflicting paths');
})();

View File

@@ -461,10 +461,12 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext()
MutableDocument addFieldsSpec;
for (auto&& [fieldName, function] : _executableOutputs) {
try {
// Wrap the projected value in a $literal since there are limitations on a user-facing
// $addFields that we don't want to enforce here (e.g. empty object).
addFieldsSpec.addField(fieldName, Value(DOC("$literal" << function->getNext())));
} catch (const DBException&) {
// If we hit a uassert while evaluating expressions on user data, delete the temporary
// table before aborting the operation.
addFieldsSpec.addField(fieldName, function->getNext());
} catch (const DBException&) {
_iterator.finalize();
throw;
}
@@ -506,6 +508,7 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext()
_iterator.finalize();
break;
}
auto projExec = projection_executor::AddFieldsProjectionExecutor::create(
pExpCtx, addFieldsSpec.freeze().toBson());