diff --git a/presto-native-execution/presto_cpp/main/common/Exception.cpp b/presto-native-execution/presto_cpp/main/common/Exception.cpp index 1cfc0e2ab3e4a..a77471161e026 100644 --- a/presto-native-execution/presto_cpp/main/common/Exception.cpp +++ b/presto-native-execution/presto_cpp/main/common/Exception.cpp @@ -78,7 +78,12 @@ VeloxToPrestoExceptionTranslator::translateMap() { {velox::error_code::kUnknown, {0x00010000, "GENERIC_INTERNAL_ERROR", - protocol::ErrorType::INTERNAL_ERROR}}}}, + protocol::ErrorType::INTERNAL_ERROR}}, + + {presto::error_code::kExceededLocalBroadcastJoinMemoryLimit, + {0x0002000C, + "EXCEEDED_LOCAL_BROADCAST_JOIN_MEMORY_LIMIT", + protocol::ErrorType::INSUFFICIENT_RESOURCES}}}}, {velox::error_source::kErrorSourceUser, {{velox::error_code::kInvalidArgument, diff --git a/presto-native-execution/presto_cpp/main/common/Exception.h b/presto-native-execution/presto_cpp/main/common/Exception.h index 6bc0d16ba28e7..cf2b954b90a98 100644 --- a/presto-native-execution/presto_cpp/main/common/Exception.h +++ b/presto-native-execution/presto_cpp/main/common/Exception.h @@ -27,20 +27,28 @@ struct ExecutionFailureInfo; struct ErrorCode; } // namespace protocol +namespace error_code { +using namespace folly::string_literals; + +/// An error raised when Presto broadcast join exceeds the broadcast size limit. +inline constexpr auto kExceededLocalBroadcastJoinMemoryLimit = + "EXCEEDED_LOCAL_BROADCAST_JOIN_MEMORY_LIMIT"_fs; +} // namespace error_code + class VeloxToPrestoExceptionTranslator { public: // Translates to Presto error from Velox exceptions static protocol::ExecutionFailureInfo translate( const velox::VeloxException& e); + // Translates to Presto error from std::exceptions + static protocol::ExecutionFailureInfo translate(const std::exception& e); + // Returns a reference to the error map containing mapping between // velox error code and Presto errors defined in Presto protocol static std::unordered_map< std::string, std::unordered_map>& translateMap(); - - // Translates to Presto error from std::exceptions - static protocol::ExecutionFailureInfo translate(const std::exception& e); }; } // namespace facebook::presto diff --git a/presto-native-execution/presto_cpp/main/common/tests/CommonTest.cpp b/presto-native-execution/presto_cpp/main/common/tests/CommonTest.cpp index 7da469c3b113b..0c435376663fa 100644 --- a/presto-native-execution/presto_cpp/main/common/tests/CommonTest.cpp +++ b/presto-native-execution/presto_cpp/main/common/tests/CommonTest.cpp @@ -16,6 +16,7 @@ #include "presto_cpp/main/common/Utils.h" #include "velox/common/base/Exceptions.h" +using namespace facebook; using namespace facebook::velox; using namespace facebook::presto; @@ -46,7 +47,7 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { "operator()", "test message", "", - error_code::kArithmeticError, + velox::error_code::kArithmeticError, false); EXPECT_THROW({ throw userException; }, VeloxException); @@ -55,7 +56,7 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { } catch (const VeloxException& e) { EXPECT_EQ(e.exceptionName(), "VeloxUserError"); EXPECT_EQ(e.errorSource(), error_source::kErrorSourceUser); - EXPECT_EQ(e.errorCode(), error_code::kArithmeticError); + EXPECT_EQ(e.errorCode(), velox::error_code::kArithmeticError); auto failureInfo = VeloxToPrestoExceptionTranslator::translate(e); EXPECT_EQ(failureInfo.type, e.exceptionName()); @@ -82,7 +83,7 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { "operator()", "test message", "", - error_code::kInvalidState, + velox::error_code::kInvalidState, false); EXPECT_THROW({ throw runtimeException; }, VeloxException); @@ -91,7 +92,7 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { } catch (const VeloxException& e) { EXPECT_EQ(e.exceptionName(), "VeloxRuntimeError"); EXPECT_EQ(e.errorSource(), error_source::kErrorSourceRuntime); - EXPECT_EQ(e.errorCode(), error_code::kInvalidState); + EXPECT_EQ(e.errorCode(), velox::error_code::kInvalidState); auto failureInfo = VeloxToPrestoExceptionTranslator::translate(e); EXPECT_EQ(failureInfo.type, e.exceptionName()); @@ -107,7 +108,7 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { } catch (const VeloxException& e) { EXPECT_EQ(e.exceptionName(), "VeloxUserError"); EXPECT_EQ(e.errorSource(), error_source::kErrorSourceUser); - EXPECT_EQ(e.errorCode(), error_code::kInvalidArgument); + EXPECT_EQ(e.errorCode(), velox::error_code::kInvalidArgument); auto failureInfo = VeloxToPrestoExceptionTranslator::translate(e); EXPECT_EQ(failureInfo.type, e.exceptionName()); @@ -129,6 +130,70 @@ TEST(VeloxToPrestoExceptionTranslatorTest, exceptionTranslation) { EXPECT_EQ(failureInfo.errorCode.type, protocol::ErrorType::INTERNAL_ERROR); } +TEST(VeloxToPrestoExceptionTranslatorTest, allErrorCodeTranslations) { + // Test all error codes in the translation map to ensure they translate + // correctly + const auto& translateMap = VeloxToPrestoExceptionTranslator::translateMap(); + + for (const auto& [errorSource, errorCodeMap] : translateMap) { + for (const auto& [errorCode, expectedErrorCode] : errorCodeMap) { + SCOPED_TRACE(fmt::format( + "errorSource: {}, errorCode: {}", errorSource, errorCode)); + + // Determine the exception type based on error source + if (errorSource == velox::error_source::kErrorSourceRuntime) { + VeloxRuntimeError runtimeException( + "test_file.cpp", + 42, + "testFunction()", + "testExpression", + "test error message", + "", + errorCode, + false); + + auto failureInfo = + VeloxToPrestoExceptionTranslator::translate(runtimeException); + + EXPECT_EQ(failureInfo.errorCode.code, expectedErrorCode.code) + << "Error code mismatch for " << errorCode; + EXPECT_EQ(failureInfo.errorCode.name, expectedErrorCode.name) + << "Error name mismatch for " << errorCode; + EXPECT_EQ(failureInfo.errorCode.type, expectedErrorCode.type) + << "Error type mismatch for " << errorCode; + EXPECT_EQ(failureInfo.type, "VeloxRuntimeError"); + EXPECT_EQ(failureInfo.errorLocation.lineNumber, 42); + + } else if (errorSource == velox::error_source::kErrorSourceUser) { + VeloxUserError userException( + "test_file.cpp", + 42, + "testFunction()", + "testExpression", + "test error message", + "", + errorCode, + false); + + auto failureInfo = + VeloxToPrestoExceptionTranslator::translate(userException); + + EXPECT_EQ(failureInfo.errorCode.code, expectedErrorCode.code) + << "Error code mismatch for " << errorCode; + EXPECT_EQ(failureInfo.errorCode.name, expectedErrorCode.name) + << "Error name mismatch for " << errorCode; + EXPECT_EQ(failureInfo.errorCode.type, expectedErrorCode.type) + << "Error type mismatch for " << errorCode; + EXPECT_EQ(failureInfo.type, "VeloxUserError"); + EXPECT_EQ(failureInfo.errorLocation.lineNumber, 42); + + } else if (errorSource == velox::error_source::kErrorSourceSystem) { + FAIL(); + } + } + } +} + TEST(UtilsTest, general) { EXPECT_EQ("2021-05-20T19:18:27.001Z", util::toISOTimestamp(1621538307001l)); EXPECT_EQ("2021-05-20T19:18:27.000Z", util::toISOTimestamp(1621538307000l)); @@ -144,4 +209,4 @@ TEST(UtilsTest, extractMessageBody) { body.push_back(std::move(iobuf)); auto messageBody = util::extractMessageBody(body); EXPECT_EQ(messageBody, "body1body2body3body4body5"); -} \ No newline at end of file +}