mirror of
https://github.com/FerretDB/documentdb.git
synced 2026-11-06 19:12:50 -05:00
### Does this PR have any customer impact? ### Type (Feature, Refactoring, Bugfix, DevOps, Testing, Perf, etc) ### Does it involve schema level changes? (Table, Column, Index, UDF, etc level changes) ### 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 draft update error msg ---- #### AI description (iteration 1) #### PR Classification This is a code cleanup and bug‑fix pull request that standardizes and clarifies error messages and log details across multiple modules. #### PR Summary The changes improve the consistency, clarity, and accuracy of user‑facing messages and logging throughout the code base. Key changes include: - In files under directories such as `oss/internal/pg_documentdb_distributed/src/test/regress/expected/` and `pgmongo/src/test/docdb_compat/expected/`, error messages for geospatial query operators (e.g. geoNear, $center, $within) and aggregation stage operators have been rewritten for clarity (e.g. replacing vague “Too many geoNear expressions” with “Excessive number of geoNear query expressions” and clarifying numeric parameter validations). - Several operators’ messages (e.g. `$cond`, `$not`, `$abs`, `$floor`, `$divide`, `$log`, etc.) have been updated to state exactly how many arguments are required, using <!-- GitOpsUserAgent=GitOps.Apps.Server.pullrequestcopilot -->
224 lines
6.2 KiB
C
224 lines
6.2 KiB
C
/*-------------------------------------------------------------------------
|
|
* Copyright (c) Microsoft Corporation. All rights reserved.
|
|
*
|
|
* include/commands/parse_error.h
|
|
*
|
|
* Errors thrown for common parse errors.
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#include <postgres.h>
|
|
|
|
#include "io/bson_core.h"
|
|
#include "utils/documentdb_errors.h"
|
|
|
|
|
|
#ifndef PARSE_ERROR_H
|
|
#define PARSE_ERROR_H
|
|
|
|
|
|
static inline void
|
|
ThrowTopLevelTypeMismatchError(const char *fieldName, const char *fieldTypeName,
|
|
const char *expectedTypeName)
|
|
{
|
|
ereport(ERROR, (errcode(ERRCODE_DOCUMENTDB_TYPEMISMATCH),
|
|
errmsg(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be of type '%s'.",
|
|
fieldName, fieldTypeName, expectedTypeName),
|
|
errdetail_log(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be of type '%s'.",
|
|
fieldName, fieldTypeName, expectedTypeName)));
|
|
}
|
|
|
|
|
|
/*
|
|
* Throw an error if type of the value that given iterator holds doesn't
|
|
* match the expected one.
|
|
*/
|
|
static inline void
|
|
EnsureTopLevelFieldType(const char *fieldName, const bson_iter_t *iter,
|
|
bson_type_t expectedType)
|
|
{
|
|
bson_type_t fieldType = bson_iter_type(iter);
|
|
if (fieldType != expectedType)
|
|
{
|
|
ThrowTopLevelTypeMismatchError(fieldName, BsonTypeName(fieldType),
|
|
BsonTypeName(expectedType));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Variant of the above with values.
|
|
*/
|
|
static inline void
|
|
EnsureTopLevelFieldValueType(const char *fieldName, const bson_value_t *value,
|
|
bson_type_t expectedType)
|
|
{
|
|
if (value->value_type != expectedType)
|
|
{
|
|
ThrowTopLevelTypeMismatchError(fieldName, BsonTypeName(value->value_type),
|
|
BsonTypeName(expectedType));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Similar to EnsureTopLevelFieldType, but null value is also ok even if
|
|
* expectedType is not "null".
|
|
*
|
|
* That means;
|
|
* - Returns true if type of the value that it holds matches the expected
|
|
* one.
|
|
* - Otherwise, returns false if iterator holds null value else throws an
|
|
* error.
|
|
*
|
|
* Mostly useful when given field being set to null implies using the default
|
|
* setting for that spec option.
|
|
*/
|
|
static inline bool
|
|
EnsureTopLevelFieldTypeNullOk(const char *fieldName, const bson_iter_t *iter,
|
|
bson_type_t expectedType)
|
|
{
|
|
if (BSON_ITER_HOLDS_NULL(iter) && expectedType != BSON_TYPE_NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
EnsureTopLevelFieldType(fieldName, iter, expectedType);
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Similar to EnsureTopLevelFieldType, but null value is also ok even if
|
|
* expectedType is not "null" or "undefined".
|
|
*
|
|
* That means;
|
|
* - Returns true if type of the value that it holds matches the expected
|
|
* one.
|
|
* - Otherwise, returns false if iterator holds null value else throws an
|
|
* error.
|
|
*
|
|
* Mostly useful when given field being set to null implies using the default
|
|
* setting for that spec option.
|
|
*/
|
|
static inline bool
|
|
EnsureTopLevelFieldTypeNullOkUndefinedOK(const char *fieldName, const bson_iter_t *iter,
|
|
bson_type_t expectedType)
|
|
{
|
|
if ((BSON_ITER_HOLDS_NULL(iter) && expectedType != BSON_TYPE_NULL) ||
|
|
(BSON_ITER_HOLDS_UNDEFINED(iter) && expectedType != BSON_TYPE_UNDEFINED))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
EnsureTopLevelFieldType(fieldName, iter, expectedType);
|
|
return true;
|
|
}
|
|
|
|
|
|
/*
|
|
* Throw an error if type of the value that given iterator holds cannot be
|
|
* interpreted as a boolean.
|
|
*/
|
|
static inline void
|
|
EnsureTopLevelFieldIsBooleanLike(const char *fieldName, const bson_iter_t *iter)
|
|
{
|
|
if (!BsonTypeIsNumberOrBool(bson_iter_type(iter)))
|
|
{
|
|
ereport(ERROR, (errcode(ERRCODE_DOCUMENTDB_TYPEMISMATCH),
|
|
errmsg(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be"
|
|
" one of the following valid types: [bool, long, int, decimal, double]",
|
|
fieldName, BsonIterTypeName(iter)),
|
|
errdetail_log(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be"
|
|
" one of the following valid types: [bool, long, int, decimal, double]",
|
|
fieldName, BsonIterTypeName(iter))));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Throw an error if type of the value that given iterator holds cannot be
|
|
* interpreted as a number.
|
|
*/
|
|
static inline void
|
|
EnsureTopLevelFieldIsNumberLike(const char *fieldName, const bson_value_t *value)
|
|
{
|
|
if (!BsonTypeIsNumber(value->value_type))
|
|
{
|
|
ereport(ERROR, (errcode(ERRCODE_DOCUMENTDB_TYPEMISMATCH),
|
|
errmsg(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be"
|
|
" one of the following valid types: [int, decimal, double, long]",
|
|
fieldName, BsonTypeName(value->value_type)),
|
|
errdetail_log(
|
|
"The BSON field '%s' has an incorrect type '%s'; it should be"
|
|
" one of the following valid types: [int, decimal, double, long]",
|
|
fieldName, BsonTypeName(value->value_type))));
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Similar to EnsureTopLevelFieldIsBooleanLike, but null value is also ok.
|
|
*
|
|
* That means;
|
|
* - Returns true if type of the value that it holds can be interpreted as
|
|
* a boolean.
|
|
* - Otherwise, returns false if iterator holds null value else throws an
|
|
* error.
|
|
*
|
|
* Mostly useful when given field being set to null implies using the default
|
|
* setting for that spec option.
|
|
*/
|
|
static inline bool
|
|
EnsureTopLevelFieldIsBooleanLikeNullOk(const char *fieldName, const bson_iter_t *iter)
|
|
{
|
|
if (BSON_ITER_HOLDS_NULL(iter))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
EnsureTopLevelFieldIsBooleanLike(fieldName, iter);
|
|
return true;
|
|
}
|
|
|
|
|
|
static inline void
|
|
ThrowTopLevelMissingFieldError(const char *fieldName)
|
|
{
|
|
ereport(ERROR, (errcode(ERRCODE_DOCUMENTDB_BADVALUE),
|
|
errmsg("The BSON field '%s' is required but was not provided",
|
|
fieldName)));
|
|
}
|
|
|
|
|
|
static inline void
|
|
ThrowTopLevelMissingFieldErrorWithCode(const char *fieldName, int code)
|
|
{
|
|
ereport(ERROR, (errcode(code),
|
|
errmsg("The BSON field '%s' is required but was not provided",
|
|
fieldName),
|
|
errdetail_log("The BSON field '%s' is required but was not provided",
|
|
fieldName)));
|
|
}
|
|
|
|
|
|
static inline void
|
|
EnsureStringValueNotDollarPrefixed(const char *fieldValue, int fieldLength)
|
|
{
|
|
if (fieldLength > 0 && fieldValue[0] == '$')
|
|
{
|
|
ereport(ERROR, (
|
|
errcode(ERRCODE_DOCUMENTDB_LOCATION16410),
|
|
errmsg(
|
|
"FieldPath field names are not allowed to begin with the operators symbol '$'; consider using $getField or $setField instead.")));
|
|
}
|
|
}
|
|
|
|
|
|
#endif
|