diff options
Diffstat (limited to 'src/mongo/db/pipeline/document_source_set_window_fields.cpp')
| -rw-r--r-- | src/mongo/db/pipeline/document_source_set_window_fields.cpp | 45 |
1 files changed, 21 insertions, 24 deletions
diff --git a/src/mongo/db/pipeline/document_source_set_window_fields.cpp b/src/mongo/db/pipeline/document_source_set_window_fields.cpp index e32fc78c04b..45223bb1cf4 100644 --- a/src/mongo/db/pipeline/document_source_set_window_fields.cpp +++ b/src/mongo/db/pipeline/document_source_set_window_fields.cpp @@ -144,8 +144,8 @@ WindowFunctionStatement WindowFunctionStatement::parse(BSONElement elem, window_function::Expression::parse(elem.embeddedObject(), sortBy, expCtx)); } void WindowFunctionStatement::serialize(MutableDocument& outputFields, - const SerializationOptions& opts) const { - outputFields[opts.serializeFieldPathFromString(fieldName)] = expr->serialize(opts); + boost::optional<ExplainOptions::Verbosity> explain) const { + outputFields[fieldName] = expr->serialize(explain); } list<intrusive_ptr<DocumentSource>> document_source_set_window_fields::create( @@ -218,10 +218,12 @@ list<intrusive_ptr<DocumentSource>> document_source_set_window_fields::create( } else { // In DocumentSource we don't have a mechanism for generating non-colliding field names, // so we have to choose the tmp name carefully to make a collision unlikely in practice. - auto tmp = "__internal_setWindowFields_partition_key"; - simplePartitionBy = FieldPath{tmp}; + std::array<unsigned char, 16> nonce = UUID::gen().data(); + // We encode as a base64 string for a shorter, more performant field name (length 22). + std::string tmpField = base64::encode(nonce.data(), sizeof(nonce)); + simplePartitionBy = FieldPath{tmpField}; simplePartitionByExpr = ExpressionFieldPath::createPathFromString( - expCtx.get(), tmp, expCtx->variablesParseState); + expCtx.get(), tmpField, expCtx->variablesParseState); complexPartitionBy = partitionBy; } } @@ -286,38 +288,39 @@ intrusive_ptr<DocumentSource> DocumentSourceInternalSetWindowFields::optimize() return this; } -Value DocumentSourceInternalSetWindowFields::serialize(const SerializationOptions& opts) const { +Value DocumentSourceInternalSetWindowFields::serialize( + boost::optional<ExplainOptions::Verbosity> explain) const { MutableDocument spec; spec[SetWindowFieldsSpec::kPartitionByFieldName] = - _partitionBy ? (*_partitionBy)->serialize(opts) : Value(); + _partitionBy ? (*_partitionBy)->serialize(false) : Value(); - auto sortKeySerialization = opts.verbosity + auto sortKeySerialization = explain ? SortPattern::SortKeySerialization::kForExplain : SortPattern::SortKeySerialization::kForPipelineSerialization; spec[SetWindowFieldsSpec::kSortByFieldName] = - _sortBy ? Value(_sortBy->serialize(sortKeySerialization, opts)) : Value(); + _sortBy ? Value(_sortBy->serialize(sortKeySerialization)) : Value(); MutableDocument output; for (auto&& stmt : _outputFields) { - stmt.serialize(output, opts); + stmt.serialize(output, explain); } spec[SetWindowFieldsSpec::kOutputFieldName] = output.freezeToValue(); MutableDocument out; out[getSourceName()] = Value(spec.freeze()); - if (opts.verbosity && *opts.verbosity >= ExplainOptions::Verbosity::kExecStats) { + if (explain && *explain >= ExplainOptions::Verbosity::kExecStats) { MutableDocument md; for (auto&& [fieldName, function] : _executableOutputs) { - md[opts.serializeFieldPathFromString(fieldName)] = opts.serializeLiteral( - static_cast<long long>(_memoryTracker[fieldName].maxMemoryBytes())); + md[fieldName] = + Value(static_cast<long long>(_memoryTracker[fieldName].maxMemoryBytes())); } out["maxFunctionMemoryUsageBytes"] = Value(md.freezeToValue()); out["maxTotalMemoryUsageBytes"] = - opts.serializeLiteral(static_cast<long long>(_memoryTracker.maxMemoryBytes())); - out["usedDisk"] = opts.serializeLiteral(_iterator.usedDisk()); + Value(static_cast<long long>(_memoryTracker.maxMemoryBytes())); + out["usedDisk"] = Value(_iterator.usedDisk()); } return Value(out.freezeToValue()); @@ -461,12 +464,8 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext() return DocumentSource::GetNextResult::makeEOF(); auto curDoc = _iterator.current(); + // The only way we hit this case is if there are no documents, since otherwise _eof will be set. if (!curDoc) { - if (_iterator.isPaused()) { - return DocumentSource::GetNextResult::makePauseExecution(); - } - // The only way we hit this case is if there are no documents, since otherwise _eof will be - // set. _eof = true; return DocumentSource::GetNextResult::makeEOF(); } @@ -474,15 +473,13 @@ DocumentSource::GetNextResult DocumentSourceInternalSetWindowFields::doGetNext() // Populate the output document with the result from each window function. auto projSpec = std::make_unique<projection_executor::InclusionNode>( ProjectionPolicies{ProjectionPolicies::DefaultIdPolicy::kIncludeId}); - for (auto&& outputField : _outputFields) { + for (auto&& [fieldName, function] : _executableOutputs) { try { // If we hit a uassert while evaluating expressions on user data, delete the temporary // table before aborting the operation. - auto& fieldName = outputField.fieldName; projSpec->addExpressionForPath( FieldPath(fieldName), - ExpressionConstant::create(pExpCtx.get(), - _executableOutputs[fieldName]->getNext())); + ExpressionConstant::create(pExpCtx.get(), function->getNext())); } catch (const DBException&) { _iterator.finalize(); throw; |
