Files
mongo/jstests/multiVersion/targetedTestsLastLtsFeatures/bindata_convert_numeric_view_upgrade_downgrade.js
Charlie Swanson bad5171545 SERVER-97919 Enable featureFlagRankFusionBasic by default. (#31487)
GitOrigin-RevId: ed9229520a78eef8e04588452ddf594698506faf
2025-01-24 04:22:19 +00:00

275 lines
9.0 KiB
JavaScript

/**
* Verifies that BinData $convert behaves correctly in FCV upgrade/downgrade scenarios.
*/
import {assertDropAndRecreateCollection} from "jstests/libs/collection_drop_recreate.js";
import {
testPerformUpgradeDowngradeReplSet
} from "jstests/multiVersion/libs/mixed_version_fixture_test.js";
import {
testPerformUpgradeDowngradeSharded
} from "jstests/multiVersion/libs/mixed_version_sharded_fixture_test.js";
const collectionName = "coll";
const toIntViewName = "toIntView";
const toIntPipeline = [{$project: {intFromBindata: {$toInt: "$asBinData"}}}];
const toLongViewName = "toLongView";
const toLongPipeline = [{$project: {longFromBindata: {$toLong: "$asBinData"}}}];
const toDoubleViewName = "toDoubleView";
const toDoublePipeline = [{$project: {doubleFromBindata: {$toDouble: "$asBinData"}}}];
const getDB = (primaryConnection) => primaryConnection.getDB(jsTestName());
function setupCollection(primaryConnection, shardingTest = null) {
const coll = assertDropAndRecreateCollection(getDB(primaryConnection), collectionName);
if (shardingTest) {
shardingTest.shardColl(coll, {asBinData: 1}, false);
}
assert.commandWorked(coll.insertMany([
{
_id: 0,
asInt: NumberInt(42),
asBinData: BinData(0, "AAAAKg=="),
},
{
_id: 1,
asLong: NumberLong(674),
asBinData: BinData(0, "ogIAAA=="),
},
{
_id: 2,
asDouble: 13.199999809265137,
asBinData: BinData(0, "QVMzMw=="),
},
]));
}
function assertViewCanBeCreatedButNotExecuted(primaryConnection) {
const db = getDB(primaryConnection);
// View creation succeeds, but queries on the views fail due to unsupported bindata-to-int,
// bindata-to-double and bindata-to-long conversions.
db[toIntViewName].drop();
assert.commandWorked(db.createView(toIntViewName, collectionName, toIntPipeline));
assert.commandFailedWithCode(db.runCommand({find: toIntViewName, filter: {}}),
ErrorCodes.ConversionFailure);
db[toLongViewName].drop();
assert.commandWorked(db.createView(toLongViewName, collectionName, toLongPipeline));
assert.commandFailedWithCode(db.runCommand({find: toLongViewName, filter: {}}),
ErrorCodes.ConversionFailure);
db[toDoubleViewName].drop();
assert.commandWorked(db.createView(toDoubleViewName, collectionName, toDoublePipeline));
assert.commandFailedWithCode(db.runCommand({find: toDoubleViewName, filter: {}}),
ErrorCodes.ConversionFailure);
}
function assertViewCanBeCreatedAndExecuted(primaryConnection) {
const db = getDB(primaryConnection);
db[toIntViewName].drop();
assert.commandWorked(db.createView(toIntViewName, collectionName, toIntPipeline));
assert.commandWorked(db.runCommand({find: toIntViewName, filter: {}}));
db[toLongViewName].drop();
assert.commandWorked(db.createView(toLongViewName, collectionName, toLongPipeline));
assert.commandWorked(db.runCommand({find: toLongViewName, filter: {}}));
db[toDoubleViewName].drop();
assert.commandWorked(db.createView(toDoubleViewName, collectionName, toDoublePipeline));
assert.commandWorked(db.runCommand({find: toDoubleViewName, filter: {}}));
}
function assertQueriesOnViewsFail(primaryConnection) {
const db = getDB(primaryConnection);
// Queries on views using BinData $convert numeric should fail after downgrading the FCV.
assert.commandFailedWithCode(db.runCommand({find: toIntViewName, filter: {}}),
ErrorCodes.ConversionFailure);
assert.commandFailedWithCode(db.runCommand({find: toLongViewName, filter: {}}),
ErrorCodes.ConversionFailure);
assert.commandFailedWithCode(db.runCommand({find: toDoubleViewName, filter: {}}),
ErrorCodes.ConversionFailure);
// BinData to int / long / double conversion still succeeds with onError value.
assert.commandWorked(db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
intFromBindata: {
$convert: {
input: "$asBinData",
to: "int",
onError: "NULL",
}
}
}
}]
}));
assert.commandWorked(db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
longFromBindata: {
$convert: {
input: "$asBinData",
to: "long",
onError: "NULL",
}
}
}
}]
}));
assert.commandWorked(db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
doubleFromBindata: {
$convert: {
input: "$asBinData",
to: "double",
onError: "NULL",
}
}
}
}]
}));
// However, they should not succeed with a 'byteOrder' argument.
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
stringFromUuid: {
$convert: {
input: "$asBinData",
to: "int",
byteOrder: "little",
onError: "NULL",
}
}
}
}]
}),
ErrorCodes.FailedToParse,
);
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
longFromBinData: {
$convert: {
input: "$asBinData",
to: "long",
byteOrder: "big",
onError: "NULL",
}
}
}
}]
}),
ErrorCodes.FailedToParse,
);
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
doubleFromBinData: {
$convert: {
input: "$asBinData",
to: "double",
byteOrder: "big",
onError: "NULL",
}
}
}
}]
}),
ErrorCodes.FailedToParse,
);
// Int, long and double to BinData should fail
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
BinDataFromInt: {
$convert: {
input: "$asInt",
to: "binData",
}
}
}
}]
}),
ErrorCodes.ConversionFailure,
);
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
BinDataFromInt:
{$convert: {input: "$asLong", to: "binData", byteOrder: "little"}}
}
}]
}),
ErrorCodes.FailedToParse,
);
assert.commandFailedWithCode(
db.runCommand({
aggregate: collectionName,
cursor: {},
pipeline: [{
$project: {
BinDataFromDouble:
{$convert: {input: "$asDouble", to: "binData", byteOrder: "little"}}
}
}]
}),
ErrorCodes.FailedToParse,
);
}
testPerformUpgradeDowngradeReplSet({
setupFn: setupCollection,
whenFullyDowngraded: assertViewCanBeCreatedButNotExecuted,
whenSecondariesAreLatestBinary: assertViewCanBeCreatedButNotExecuted,
whenBinariesAreLatestAndFCVIsLastLTS: assertQueriesOnViewsFail,
whenFullyUpgraded: assertViewCanBeCreatedAndExecuted,
});
testPerformUpgradeDowngradeSharded({
setupFn: setupCollection,
whenFullyDowngraded: assertViewCanBeCreatedButNotExecuted,
whenOnlyConfigIsLatestBinary: assertViewCanBeCreatedButNotExecuted,
whenSecondariesAndConfigAreLatestBinary: assertViewCanBeCreatedButNotExecuted,
whenMongosBinaryIsLastLTS: assertQueriesOnViewsFail,
whenBinariesAreLatestAndFCVIsLastLTS: assertQueriesOnViewsFail,
whenFullyUpgraded: assertViewCanBeCreatedAndExecuted,
});