Files
documentdb/pg_documentdb/include/query/query_operator.h
T
Vinod Sridharan 8261e772f4 Merged PR 1672946: [Update] Make update parsing cheaper
### Does this PR have any customer impact?
Yes
### Type (Feature, Refactoring, Bugfix, DevOps, Testing, Perf, etc)
Perf
### Does it involve schema level changes? (Table, Column, Index, UDF, etc level changes)
No
### Are you introducing any new config? If yes, do you have tests with and without them being set?

### ChangeLog (Refer [Template](../oss/CHANGELOG.md))

### Description

Currently for Update/Delete, we currently parse the update spec, query spec, etc into pgbsons on startup. Then reuse it per commands.

This has a few issues - for large document requests, this causes us to duplicate memory and persist it for the duration of the update and also transcode all up front - this is worse for multi-node when all we need to do is build yet another update spec and push it to the worker.

Instead, we now only cache pointers to the spec document; then when we need it we convert to pgbson only if necessary.

A consequence of this is that on a single node update, if we're doing a simple updateOne on _id then we would never serialize the updateSpec at all (for instance).

We also more eagerly free memory on the intermediate update specs.

----
#### AI description  (iteration 1)
#### PR Classification
Performance optimization for update parsing by refactoring BSON value handling.

#### PR Summary
This PR streamlines update parsing by replacing heavy BSON initialization routines with lightweight wrappers and converting update-related types from `pgbson*` to `bson_value_t*`, which reduces overhead and improves coordinator/worker compatibility.
- `src/commands/update.c`: Replaced multiple `PgbsonInitFromDocumentBsonValue` and similar calls with efficient wrappers like `CreateBsonValueFrom` and updated serialization (including back-compatible array filter and update document formats).
- `include/commands/update.h`: Updated update structure fields to use `bson_value_t*` instead of `pgbson*`, aligning interfaces with the new parsing approach.
- `src/update/bson_update.c` and `bson_update_operators_workflow.c`: Refactored update type determination and replace document logic to use new BSON value iterators and helper functions.
- Other modules (e.g. `commands/find_and_modify.c`, `commands/delete.c`, query operators, sharding) were updated to leverage the lighter-weight BSON representation and its associated helper routines.
<!-- GitOpsUserAgent=GitOps.Apps.Server.pullrequestcopilot -->
2025-05-29 12:12:31 +08:00

147 lines
5.2 KiB
C

/*-------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* src/bson_query.h
*
* Common declarations for BSON query functions.
*
*-------------------------------------------------------------------------
*/
#ifndef QUERY_OPERATOR_H
#define QUERY_OPERATOR_H
#include <nodes/params.h>
#include <nodes/parsenodes.h>
#include "metadata/collection.h"
#include "io/bson_core.h"
#include "opclass/bson_gin_common.h"
#include "planner/mongo_query_operator.h"
/* BsonElemMatchContext is passed down while expanding BSON query expressions to handle $elemMatch operator */
typedef struct BsonElemMatchContext
{
/* Depth in case of nested elemMatch while traversing the query */
int currentDepth;
/* Max Depth in case of nested elemMatch */
int maxDepth;
/* List of quals to be applied as outermost quals in elemMatch query tree
* Example: { a: {$elemMatch: {d: {$elemMatch: {e: {$gte: 1}}}, b: {$elemMatch: { $gte: 80, $lt: 85 }}}} }
* The outermost quals will be {"a.d.e" : {"$gte" : 1}, "a.b" : {"$gte" : 80}, "a.b" : {"$lt" : 85} }
*/
List *outerMostExpressionQuals;
/* It is set when bson query expression results in SUBLINK creation in query tree */
bool hasSublink;
/* It is set when bson query expression contains number field inside $elemMatch
* Example: {"a" : { "$elemMatch": { "0" : 100 } } }
*/
bool hasNumberField;
/* It is set when there is expression inside $elemMatch for $ne, $not */
bool hasNegationOp;
/* isCmpOpInsideElemMatch : it will be set to true when there is a cmp operator inside $elemMatch i.e. for calling CreateOpExprFromOperatorDocIterator.
* {path : {$elemMatch : {$op : {...}}}}. we are interested in $op being another $elemMatch for array of array scenario.
*/
bool isCmpOpInsideElemMatch;
} BsonElemMatchContext;
/*
* BsonQueryOperatorContext is passed down while expanding BSON query expressions
* of the form <document> @@ <query>
*/
typedef struct BsonQueryOperatorContext
{
Expr *documentExpr;
/* The input variable type for functions. Note that this should
* match the data type expectations of documentExpr above.
* If documentExpr is bson -> this is bson (otherwise it's bsonValue)
*/
MongoQueryOperatorInputType inputType;
/*
* Whether or not to treat a simple $or as $in.
*/
bool simplifyOperators;
/*
* Coerce expressions to runtime OpExpr if available
*/
bool coerceOperatorExprIfApplicable;
/* Required path names for vector search
* it is set only when the filter of vector search is specified
*/
HTAB *requiredFilterPathNameHashSet;
/* List of sort clauses, if any query operator adds them
* e.g. $near, $nearSphere etc, will be NULL for most of
* the query operators.
*
* Please note that the `ressortgroupref` is needed to be updated
* based on the overall query structure later
*/
List *sortClauses;
/* List of Target entries for these sort clauses
*
* Please note that the `resno` is needed to be updated
* based on the overall query structure later
*/
List *targetEntries;
/* Any let variable context for this query operator */
Expr *variableContext;
/* ICU standard colation string. See AggregationPipelineBuildContext for more details. */
const char *collationString;
/* The following query operators cannot be used to evaluate input values during schema validation.
* $expr with $function expressions / $near / $nearSphere / $text / $where
*/
bool hasOperatorRestrictions;
} BsonQueryOperatorContext;
Var * MakeSimpleDocumentVar(void);
Node * ReplaceBsonQueryOperators(Query *node, ParamListInfo boundParams);
void ValidateQueryDocumentValue(const bson_value_t *queryDocumentValue);
void ValidateQueryDocument(pgbson *queryDocument);
bool QueryDocumentsAreEquivalent(const pgbson *leftQueryDocument,
const pgbson *rightQueryDocument);
List * CreateQualsFromQueryDocIterator(bson_iter_t *queryDocIterator,
BsonQueryOperatorContext *context);
Node * EvaluateBoundParameters(Node *expression, ParamListInfo boundParams);
List * CreateQualsForBsonValueTopLevelQueryIter(bson_iter_t *queryIter);
Expr * CreateQualForBsonValueExpression(const bson_value_t *expression, const
char *collationString);
Expr * CreateQualForBsonValueArrayExpression(const bson_value_t *expression);
void BsonQueryOperatorContextCommonBuilder(BsonQueryOperatorContext *context);
Expr * CreateQualForBsonExpression(const bson_value_t *expression, const char *queryPath,
BsonQueryOperatorContext *context);
Expr * CreateNonShardedShardKeyValueFilter(int collectionVarNo, const
MongoCollection *collection);
Expr * CreateShardKeyFiltersForQuery(const bson_value_t *queryDocument, pgbson *shardKey,
uint64_t collectionId, Index collectionVarno,
bool *isShardKeyCollationAware);
Expr * CreateIdFilterForQuery(List *existingQuals,
Index collectionVarno, bool *isCollationAware,
bool *isPointRead);
bool ValidateOrderbyExpressionAndGetIsAscending(pgbson *orderby);
/* Checks the validity of value for $in and $nin ops */
bool IsValidBsonDocumentForDollarInOrNinOp(const bson_value_t *value);
void UpdateQueryOperatorContextSortList(Query *query, List *sortClauses,
List *targetEntries);
#endif