Files
documentdb/pg_helio_api/include/query/query_operator.h
T
Jayanta Mondal d3c5128254 Merged PR 1405332: Mongo collation support Part 1 ( Find/Aggregate queries with runtime collation)
### Does this PR have any customer impact?
Yes

### Type (Feature, Refactoring, Bugfix, DevOps, Testing, Perf, etc)
Feature

### 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?
Yes (helio_api.enableCollation). Yes.

### Release Note (Refer [Template](../docs/release_notes/pgmongo_template.md))
Done

### Description

Runtime implementation of collation support in Mongo Find query.

We parse the Mongo collation spec and covert it to an ICU standard collation string. An example string is "und-u-ks-level1-kc-true  This string uniquely identify collation-based string comparison logic by Postgres.  See: https://www.postgresql.org/docs/current/collation.html

This document tracks the current support matrix for query operators

| Operator  | Runtime | Index Pushdown | Comments
| --------- | ---- | ----- | ----
|  $eq | Yes | No |
|  $gt | Yes |  No |
|  $gte | Yes | No |
|  $lt | Yes |  No |
|  $lte | Yes |  No |
|  $ne | Yes |  No |
|  $in | No* |  No | See below
|  $nin | No* |  No | Do
|  $and | Yes |  No |
|  $not | Yes |  No |
|  $nor | Yes |  No |
|  $or | Yes |  No |
|  $all | Yes |  No |
|  $elemMatch |  Yes   |  No |
|  $positional | N/A | N/A | positional query operators are only used in projections.
|  $regex | N/A |  N/A   | $regex ignores collations in Native Mongo
|  $exists | N/A  |   N/A   |
|  $size | N/A  |  N/A |
|  $type | N/A |   N/A |
|  $bitsAllClear | N/A  |  N/A  | Not relevant for Utf8
|  $bitsAnyClear | N/A  |  N/A  | Do
|  $bitsAllSet | N/A  |  N/A  | Do
|  $bitsAnySet |  N/A |  N/A  | Do
|  $mod | N/A  |  N/A  | Do
|  $range | N/A  |  N/A | Only applies to Number
|  $text | N/A  |  N/A  | Seprate Index, has its own collation spec
|  $geowithin | N/A   |  N/A  | Not relevant for Utf8
|  $geointersects | N/A    | N/A   | Do

* $in/$nin is implemented with HashMap that does not support collation friendly Hashkeys
* $regex : collations are ignored with
* $text: $text spec has collation specific parameters
* $rage: For numbers only

This document tracks the current support matrix for update operators/commands

| Operator  | Runtime | Index Pushdown |
| --------- | ---- | ----- |
|  find_and_modify | No | No |
|  updateOne | No |  No |
|  updateMany | No | No |
|  createIndex | No | No |

Tests:
1. All Gated Tests pass when Collation is enabled by default

TODO:
1. Index support [already implemented - but breaking down for easy review]
2. Persist collation info while collection created [already implemented - but breaking down for easy review]
3. $cond, $let

Related work items: #3412359
2024-08-26 13:12:13 +03:00

137 lines
4.7 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/helio_bson_core.h"
#include "opclass/helio_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;
} BsonQueryOperatorContext;
Var * MakeSimpleDocumentVar(void);
Node * ReplaceBsonQueryOperators(Query *node, ParamListInfo boundParams);
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 * CreateQualsForBsonValueTopLevelQuery(const pgbson *query);
Expr * CreateQualForBsonValueExpression(const bson_value_t *expression, const
char *collationString);
Expr * CreateQualForBsonValueArrayExpression(const bson_value_t *expression);
Expr * CreateQualForBsonExpression(const bson_value_t *expression, const char *queryPath);
Expr * CreateNonShardedShardKeyValueFilter(int collectionVarNo, const
MongoCollection *collection);
Expr * CreateShardKeyFiltersForQuery(const bson_value_t *queryDocument, pgbson *shardKey,
uint64_t collectionId,
Index collectionVarno);
Expr * CreateIdFilterForQuery(List *existingQuals,
Index collectionVarno, bool *isCollationAware);
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