Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

misc: Extend cast tests in the expression fuzzer #12492

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions velox/expression/CastExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ Status detail::parseDecimalComponents(
// Optional exponent.
if (s[pos] == 'e' || s[pos] == 'E') {
++pos;
bool withSign = pos < size && (s[pos] == '+' || s[pos] == '-');
if (pos == size) {
return Status::UserError("The exponent part is empty.");
}
bool withSign = s[pos] == '+' || s[pos] == '-';
if (withSign && pos == size - 1) {
return Status::UserError("The exponent part only contains sign.");
}
Expand All @@ -98,17 +101,13 @@ Status detail::parseDecimalComponents(
for (auto i = static_cast<size_t>(withSign); i < size - pos; ++i) {
if (!std::isdigit(s[pos + i])) {
return Status::UserError(
"Non-digit character '{}' is not allowed in the exponent part.",
s[pos + i]);
"Non-digit character is not allowed in the exponent part.");
}
}
out.exponent = folly::to<int32_t>(folly::StringPiece(s + pos, size - pos));
return Status::OK();
}
return pos == size
? Status::OK()
: Status::UserError(
"Chars '{}' are invalid.", std::string(s + pos, size - pos));
return pos == size ? Status::OK() : Status::UserError("Chars are invalid.");
}

Status detail::parseHugeInt(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ SparkSpecialFormSignatureGenerator::getSignaturesForCast() const {
signatures.push_back(makeCastSignature(fromType, "varbinary"));
}

// Cast tinyint/smallint/integer/bigint as timestamp is supported in Spark.
for (auto fromType : {"tinyint", "smallint", "integer", "bigint"}) {
// Cast tinyint/smallint/integer/bigint/real/double as timestamp is supported
// in Spark.
for (auto fromType :
{"tinyint", "smallint", "integer", "bigint", "real", "double"}) {
signatures.push_back(makeCastSignature(fromType, "timestamp"));
}
return signatures;
Expand Down
24 changes: 24 additions & 0 deletions velox/expression/fuzzer/SpecialFormSignatureGenerator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,14 @@ void SpecialFormSignatureGenerator::addCastFromFloatingPointSignatures(
}
}

void SpecialFormSignatureGenerator::addCastFromDecimalSignatures(
const std::string& toType,
std::vector<exec::FunctionSignaturePtr>& signatures) const {
for (const auto& fromType : kDecimalTypes_) {
signatures.push_back(makeCastSignature(fromType, toType));
}
}

void SpecialFormSignatureGenerator::addCastFromVarcharSignature(
const std::string& toType,
std::vector<exec::FunctionSignaturePtr>& signatures) const {
Expand Down Expand Up @@ -163,19 +171,30 @@ SpecialFormSignatureGenerator::getSignaturesForCast() const {
for (const auto& toType : kIntegralTypes_) {
addCastFromIntegralSignatures(toType, signatures);
addCastFromFloatingPointSignatures(toType, signatures);
addCastFromDecimalSignatures(toType, signatures);
addCastFromVarcharSignature(toType, signatures);
}

// To floating-point types.
for (const auto& toType : kFloatingPointTypes_) {
addCastFromIntegralSignatures(toType, signatures);
addCastFromFloatingPointSignatures(toType, signatures);
addCastFromDecimalSignatures(toType, signatures);
addCastFromVarcharSignature(toType, signatures);
}

// To decimal type.
for (const auto& toType : kDecimalTypes_) {
addCastFromIntegralSignatures(toType, signatures);
addCastFromFloatingPointSignatures(toType, signatures);
addCastFromDecimalSignatures(toType, signatures);
addCastFromVarcharSignature(toType, signatures);
}

// To varchar type.
addCastFromIntegralSignatures("varchar", signatures);
addCastFromFloatingPointSignatures("varchar", signatures);
addCastFromDecimalSignatures("varchar", signatures);
addCastFromVarcharSignature("varchar", signatures);
addCastFromDateSignature("varchar", signatures);
addCastFromTimestampSignature("varchar", signatures);
Expand All @@ -195,6 +214,11 @@ SpecialFormSignatureGenerator::getSignaturesForCast() const {
auto from = signatures[i]->argumentTypes()[0].baseName();
auto to = signatures[i]->returnType().baseName();

// Signature parsing of nested decimal type is not supported.
if (from == "DECIMAL" || to == "DECIMAL") {
continue;
}

signatures.push_back(makeCastSignature(
fmt::format("array({})", from), fmt::format("array({})", to)));

Expand Down
16 changes: 14 additions & 2 deletions velox/expression/fuzzer/SpecialFormSignatureGenerator.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,14 @@ class SpecialFormSignatureGenerator {
const std::string& toType,
std::vector<exec::FunctionSignaturePtr>& signatures) const;

/// Generates signatures for cast from varchar to the given type and adds them
/// to signatures.
/// Generates signatures for cast from decimal types to the given type
/// and adds them to signatures.
void addCastFromDecimalSignatures(
const std::string& toType,
std::vector<exec::FunctionSignaturePtr>& signatures) const;

/// Generates signatures for cast from varchar to the given type and adds
/// them to signatures.
void addCastFromVarcharSignature(
const std::string& toType,
std::vector<exec::FunctionSignaturePtr>& signatures) const;
Expand Down Expand Up @@ -101,6 +107,12 @@ class SpecialFormSignatureGenerator {
"boolean"};

const std::vector<std::string> kFloatingPointTypes_{"real", "double"};

const std::vector<std::string> kDecimalTypes_{
"DECIMAL(6, 0)",
"DECIMAL(18, 6)",
"DECIMAL(38, 18)",
"DECIMAL(38, 38)"};
};

} // namespace facebook::velox::fuzzer
26 changes: 19 additions & 7 deletions velox/expression/tests/CastExprTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2048,7 +2048,7 @@ TEST_F(CastExprTest, varcharToDecimal) {
VARCHAR(),
DECIMAL(38, 0),
{"0.0444a"},
"Cannot cast VARCHAR '0.0444a' to DECIMAL(38, 0). Value is not a number. Chars 'a' are invalid.");
"Cannot cast VARCHAR '0.0444a' to DECIMAL(38, 0). Value is not a number.");

testThrow<std::string>(
VARCHAR(),
Expand Down Expand Up @@ -2081,29 +2081,29 @@ TEST_F(CastExprTest, varcharToDecimal) {
VARCHAR(),
DECIMAL(38, 0),
{"23e-5d"},
"Cannot cast VARCHAR '23e-5d' to DECIMAL(38, 0). Value is not a number. Non-digit character 'd' is not allowed in the exponent part.");
"Cannot cast VARCHAR '23e-5d' to DECIMAL(38, 0). Value is not a number. Non-digit character is not allowed in the exponent part.");

// Whitespaces.
testThrow<std::string>(
VARCHAR(),
DECIMAL(38, 0),
{"1. 23"},
"Cannot cast VARCHAR '1. 23' to DECIMAL(38, 0). Value is not a number. Chars ' 23' are invalid.");
"Cannot cast VARCHAR '1. 23' to DECIMAL(38, 0). Value is not a number.");
testThrow<std::string>(
VARCHAR(),
DECIMAL(12, 2),
{"-3E+ 2"},
"Cannot cast VARCHAR '-3E+ 2' to DECIMAL(12, 2). Value is not a number. Non-digit character ' ' is not allowed in the exponent part.");
"Cannot cast VARCHAR '-3E+ 2' to DECIMAL(12, 2). Value is not a number. Non-digit character is not allowed in the exponent part.");
testThrow<std::string>(
VARCHAR(),
DECIMAL(38, 0),
{"1.23 "},
"Cannot cast VARCHAR '1.23 ' to DECIMAL(38, 0). Value is not a number. Chars ' ' are invalid.");
"Cannot cast VARCHAR '1.23 ' to DECIMAL(38, 0). Value is not a number.");
testThrow<std::string>(
VARCHAR(),
DECIMAL(12, 2),
{"-3E+2 "},
"Cannot cast VARCHAR '-3E+2 ' to DECIMAL(12, 2). Value is not a number. Non-digit character ' ' is not allowed in the exponent part.");
"Cannot cast VARCHAR '-3E+2 ' to DECIMAL(12, 2). Value is not a number. Non-digit character is not allowed in the exponent part.");
testThrow<std::string>(
VARCHAR(),
DECIMAL(38, 0),
Expand All @@ -2119,7 +2119,7 @@ TEST_F(CastExprTest, varcharToDecimal) {
VARCHAR(),
DECIMAL(12, 2),
{"-3E+2.1"},
"Cannot cast VARCHAR '-3E+2.1' to DECIMAL(12, 2). Value is not a number. Non-digit character '.' is not allowed in the exponent part.");
"Cannot cast VARCHAR '-3E+2.1' to DECIMAL(12, 2). Value is not a number. Non-digit character is not allowed in the exponent part.");

testThrow<std::string>(
VARCHAR(),
Expand All @@ -2132,6 +2132,18 @@ TEST_F(CastExprTest, varcharToDecimal) {
DECIMAL(12, 2),
{"-3E-"},
"Cannot cast VARCHAR '-3E-' to DECIMAL(12, 2). Value is not a number. The exponent part only contains sign.");

testThrow<std::string>(
VARCHAR(),
DECIMAL(12, 2),
{"9e"},
"Cannot cast VARCHAR '9e' to DECIMAL(12, 2). Value is not a number. The exponent part is empty.");

testThrow<std::string>(
VARCHAR(),
DECIMAL(12, 2),
{"09{xi+yD"},
"Cannot cast VARCHAR '09{xi+yD' to DECIMAL(12, 2). Value is not a number. Chars are invalid.");
}

TEST_F(CastExprTest, castInTry) {
Expand Down
Loading