diff --git a/velox/exec/fuzzer/CMakeLists.txt b/velox/exec/fuzzer/CMakeLists.txt index fb6c80c6c00d..fbc6321efb66 100644 --- a/velox/exec/fuzzer/CMakeLists.txt +++ b/velox/exec/fuzzer/CMakeLists.txt @@ -13,7 +13,7 @@ # limitations under the License. add_library(velox_fuzzer_util DuckQueryRunner.cpp PrestoQueryRunner.cpp - FuzzerUtil.cpp) + FuzzerUtil.cpp ToSQLUtil.cpp) target_link_libraries( velox_fuzzer_util diff --git a/velox/exec/fuzzer/DuckQueryRunner.cpp b/velox/exec/fuzzer/DuckQueryRunner.cpp index 18a791f46786..acdc68ea205d 100644 --- a/velox/exec/fuzzer/DuckQueryRunner.cpp +++ b/velox/exec/fuzzer/DuckQueryRunner.cpp @@ -14,62 +14,13 @@ * limitations under the License. */ #include "velox/exec/fuzzer/DuckQueryRunner.h" +#include "velox/exec/fuzzer/ToSQLUtil.h" #include "velox/exec/tests/utils/QueryAssertions.h" namespace facebook::velox::exec::test { namespace { -void appendComma(int32_t i, std::stringstream& sql) { - if (i > 0) { - sql << ", "; - } -} - -std::string toCallSql(const core::CallTypedExprPtr& call) { - std::stringstream sql; - sql << call->name() << "("; - for (auto i = 0; i < call->inputs().size(); ++i) { - appendComma(i, sql); - sql << std::dynamic_pointer_cast( - call->inputs()[i]) - ->name(); - } - sql << ")"; - return sql.str(); -} - -std::string toAggregateCallSql( - const core::CallTypedExprPtr& call, - const std::vector& sortingKeys, - const std::vector& sortingOrders, - bool distinct) { - std::stringstream sql; - sql << call->name() << "("; - - if (distinct) { - sql << "distinct "; - } - - for (auto i = 0; i < call->inputs().size(); ++i) { - appendComma(i, sql); - sql << std::dynamic_pointer_cast( - call->inputs()[i]) - ->name(); - } - - if (!sortingKeys.empty()) { - sql << " order by "; - for (auto i = 0; i < sortingKeys.size(); ++i) { - appendComma(i, sql); - sql << sortingKeys[i]->name() << " " << sortingOrders[i].toString(); - } - } - - sql << ")"; - return sql.str(); -} - bool isSupported(const TypePtr& type) { // DuckDB doesn't support nanosecond precision for timestamps. if (type->kind() == TypeKind::TIMESTAMP) { diff --git a/velox/exec/fuzzer/PrestoQueryRunner.cpp b/velox/exec/fuzzer/PrestoQueryRunner.cpp index 99791ff0cb63..a0ef32d0c3b6 100644 --- a/velox/exec/fuzzer/PrestoQueryRunner.cpp +++ b/velox/exec/fuzzer/PrestoQueryRunner.cpp @@ -25,6 +25,7 @@ #include "velox/connectors/hive/TableHandle.h" #include "velox/core/Expressions.h" #include "velox/dwio/common/WriterFactory.h" +#include "velox/exec/fuzzer/ToSQLUtil.h" #include "velox/exec/tests/utils/QueryAssertions.h" #include "velox/serializers/PrestoSerializer.h" #include "velox/type/parser/TypeParser.h" @@ -213,12 +214,6 @@ std::optional PrestoQueryRunner::toSql( namespace { -void appendComma(int32_t i, std::stringstream& sql) { - if (i > 0) { - sql << ", "; - } -} - std::string toTypeSql(const TypePtr& type) { switch (type->kind()) { case TypeKind::ARRAY: @@ -248,80 +243,6 @@ std::string toTypeSql(const TypePtr& type) { } } -std::string toCallSql(const core::CallTypedExprPtr& call); - -void toCallInputsSql( - const std::vector& inputs, - std::stringstream& sql) { - for (auto i = 0; i < inputs.size(); ++i) { - appendComma(i, sql); - - const auto& input = inputs.at(i); - if (auto field = - std::dynamic_pointer_cast( - input)) { - sql << field->name(); - } else if ( - auto call = - std::dynamic_pointer_cast(input)) { - sql << toCallSql(call); - } else if ( - auto lambda = - std::dynamic_pointer_cast(input)) { - const auto& signature = lambda->signature(); - const auto& body = - std::dynamic_pointer_cast(lambda->body()); - VELOX_CHECK_NOT_NULL(body); - - sql << "("; - for (auto j = 0; j < signature->size(); ++j) { - appendComma(j, sql); - sql << signature->nameOf(j); - } - - sql << ") -> " << toCallSql(body); - } else { - VELOX_NYI(); - } - } -} - -std::string toCallSql(const core::CallTypedExprPtr& call) { - std::stringstream sql; - sql << call->name() << "("; - toCallInputsSql(call->inputs(), sql); - sql << ")"; - return sql.str(); -} - -std::string toAggregateCallSql( - const core::CallTypedExprPtr& call, - const std::vector& sortingKeys, - const std::vector& sortingOrders, - bool distinct) { - VELOX_CHECK_EQ(sortingKeys.size(), sortingOrders.size()); - std::stringstream sql; - sql << call->name() << "("; - - if (distinct) { - sql << "distinct "; - } - - toCallInputsSql(call->inputs(), sql); - - if (!sortingKeys.empty()) { - sql << " ORDER BY "; - - for (int i = 0; i < sortingKeys.size(); i++) { - appendComma(i, sql); - sql << sortingKeys[i]->name() << " " << sortingOrders[i].toString(); - } - } - - sql << ")"; - return sql.str(); -} - std::string toWindowCallSql( const core::CallTypedExprPtr& call, bool ignoreNulls = false) { diff --git a/velox/exec/fuzzer/ToSQLUtil.cpp b/velox/exec/fuzzer/ToSQLUtil.cpp new file mode 100644 index 000000000000..638de8f0b1fa --- /dev/null +++ b/velox/exec/fuzzer/ToSQLUtil.cpp @@ -0,0 +1,99 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "velox/exec/fuzzer/ToSQLUtil.h" + +namespace facebook::velox::exec::test { + +void appendComma(int32_t i, std::stringstream& sql) { + if (i > 0) { + sql << ", "; + } +} + +void toCallInputsSql( + const std::vector& inputs, + std::stringstream& sql) { + for (auto i = 0; i < inputs.size(); ++i) { + appendComma(i, sql); + + const auto& input = inputs.at(i); + if (auto field = + std::dynamic_pointer_cast( + input)) { + sql << field->name(); + } else if ( + auto call = + std::dynamic_pointer_cast(input)) { + sql << toCallSql(call); + } else if ( + auto lambda = + std::dynamic_pointer_cast(input)) { + const auto& signature = lambda->signature(); + const auto& body = + std::dynamic_pointer_cast(lambda->body()); + VELOX_CHECK_NOT_NULL(body); + + sql << "("; + for (auto j = 0; j < signature->size(); ++j) { + appendComma(j, sql); + sql << signature->nameOf(j); + } + + sql << ") -> " << toCallSql(body); + } else { + VELOX_NYI("Unsupported input expression: {}.", input->toString()); + } + } +} + +std::string toCallSql(const core::CallTypedExprPtr& call) { + std::stringstream sql; + sql << call->name() << "("; + toCallInputsSql(call->inputs(), sql); + sql << ")"; + return sql.str(); +} + +std::string toAggregateCallSql( + const core::CallTypedExprPtr& call, + const std::vector& sortingKeys, + const std::vector& sortingOrders, + bool distinct) { + VELOX_CHECK_EQ(sortingKeys.size(), sortingOrders.size()); + std::stringstream sql; + sql << call->name() << "("; + + if (distinct) { + sql << "distinct "; + } + + toCallInputsSql(call->inputs(), sql); + + if (!sortingKeys.empty()) { + sql << " ORDER BY "; + + for (int i = 0; i < sortingKeys.size(); i++) { + appendComma(i, sql); + sql << sortingKeys[i]->name() << " " << sortingOrders[i].toString(); + } + } + + sql << ")"; + return sql.str(); +} + +} // namespace facebook::velox::exec::test diff --git a/velox/exec/fuzzer/ToSQLUtil.h b/velox/exec/fuzzer/ToSQLUtil.h new file mode 100644 index 000000000000..2175658225c6 --- /dev/null +++ b/velox/exec/fuzzer/ToSQLUtil.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) Facebook, Inc. and its affiliates. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +#pragma once + +#include "velox/core/PlanNode.h" + +namespace facebook::velox::exec::test { + +/// Appends a comma to a given stringstream if the provided integer is greater +/// than 0. +void appendComma(int32_t i, std::stringstream& sql); + +// Converts input expressions into SQL string and appends to a given +// stringstream. +void toCallInputsSql( + const std::vector& inputs, + std::stringstream& sql); + +// Converts a call expression into a SQL string. +std::string toCallSql(const core::CallTypedExprPtr& call); + +// Converts aggregate call expression into a SQL string. +std::string toAggregateCallSql( + const core::CallTypedExprPtr& call, + const std::vector& sortingKeys, + const std::vector& sortingOrders, + bool distinct); + +} // namespace facebook::velox::exec::test