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

Add kRange preceding/following frames in window fuzzer #10006

Closed
Closed
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
31 changes: 26 additions & 5 deletions velox/exec/fuzzer/AggregationFuzzerBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,14 +241,35 @@ std::vector<std::string> AggregationFuzzerBase::generateKeys(
std::vector<std::string> AggregationFuzzerBase::generateSortingKeys(
const std::string& prefix,
std::vector<std::string>& names,
std::vector<TypePtr>& types) {
std::vector<TypePtr>& types,
bool rangeFrame) {
std::vector<std::string> keys;
auto numKeys = boost::random::uniform_int_distribution<uint32_t>(1, 5)(rng_);
vector_size_t numKeys;
vector_size_t maxDepth;
std::vector<TypePtr> sortingKeyTypes = kScalarTypes;

// If frame has k-RANGE bound, only one sorting key should be present, and it
// should be a scalar type which supports '+', '-' arithmetic operations.
if (rangeFrame) {
numKeys = 1;
sortingKeyTypes = {
TINYINT(),
SMALLINT(),
INTEGER(),
BIGINT(),
HUGEINT(),
REAL(),
DOUBLE()};
maxDepth = 0;
} else {
numKeys = randInt(1, 5);
// Pick random, possibly complex, type.
maxDepth = 2;
}

for (auto i = 0; i < numKeys; ++i) {
keys.push_back(fmt::format("{}{}", prefix, i));

// Pick random, possibly complex, type.
types.push_back(vectorFuzzer_.randOrderableType(2));
types.push_back(vectorFuzzer_.randOrderableType(sortingKeyTypes, maxDepth));
names.push_back(keys.back());
}

Expand Down
6 changes: 4 additions & 2 deletions velox/exec/fuzzer/AggregationFuzzerBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -183,11 +183,13 @@ class AggregationFuzzerBase {
std::vector<TypePtr>& types);

// Similar to generateKeys, but restricts types to orderable types (i.e. no
// maps).
// maps). For k-RANGE frame bounds, rangeFrame must be set to true so only
// one sorting key is generated.
std::vector<std::string> generateSortingKeys(
const std::string& prefix,
std::vector<std::string>& names,
std::vector<TypePtr>& types);
std::vector<TypePtr>& types,
bool rangeFrame = false);

std::pair<CallableSignature, SignatureStats&> pickSignature();

Expand Down
53 changes: 2 additions & 51 deletions velox/exec/fuzzer/PrestoQueryRunner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ PrestoQueryRunner::PrestoQueryRunner(
timeout_(timeout) {
eventBaseThread_.start("PrestoQueryRunner");
pool_ = aggregatePool()->addLeafChild("leaf");
queryRunnerContext_ = std::make_shared<QueryRunnerContext>();
}

std::optional<std::string> PrestoQueryRunner::toSql(
Expand Down Expand Up @@ -352,56 +353,6 @@ std::optional<std::string> PrestoQueryRunner::toSql(
return sql.str();
}

namespace {

void appendWindowFrame(
const core::WindowNode::Frame& frame,
std::stringstream& sql) {
// TODO: Add support for k Range Frames by retrieving the original range bound
// from WindowNode.
switch (frame.type) {
case core::WindowNode::WindowType::kRange:
sql << " RANGE";
break;
case core::WindowNode::WindowType::kRows:
sql << " ROWS";
break;
default:
VELOX_UNREACHABLE();
}
sql << " BETWEEN";

auto appendBound = [&sql](
const core::WindowNode::BoundType& bound,
const core::TypedExprPtr& value) {
switch (bound) {
case core::WindowNode::BoundType::kUnboundedPreceding:
sql << " UNBOUNDED PRECEDING";
break;
case core::WindowNode::BoundType::kUnboundedFollowing:
sql << " UNBOUNDED FOLLOWING";
break;
case core::WindowNode::BoundType::kCurrentRow:
sql << " CURRENT ROW";
break;
case core::WindowNode::BoundType::kPreceding:
sql << " " << value->toString() << " PRECEDING";
break;
case core::WindowNode::BoundType::kFollowing:
sql << " " << value->toString() << " FOLLOWING";
break;
default:
VELOX_UNREACHABLE();
}
};

appendBound(frame.startType, frame.startValue);
sql << " AND";
appendBound(frame.endType, frame.endValue);
}

} // namespace

std::optional<std::string> PrestoQueryRunner::toSql(
const std::shared_ptr<const core::WindowNode>& windowNode) {
if (!isSupportedDwrfType(windowNode->sources()[0]->outputType())) {
Expand Down Expand Up @@ -446,7 +397,7 @@ std::optional<std::string> PrestoQueryRunner::toSql(
}
}

appendWindowFrame(functions[i].frame, sql);
sql << " " << queryRunnerContext_->windowFrames_.at(windowNode->id()).at(i);
sql << ")";
}

Expand Down
10 changes: 10 additions & 0 deletions velox/exec/fuzzer/PrestoQueryRunner.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@ T extractSingleValue(const std::vector<RowVectorPtr>& data) {
return simpleVector->valueAt(0);
}

class QueryRunnerContext {
public:
std::unordered_map<core::PlanNodeId, std::vector<std::string>> windowFrames_;
};

class PrestoQueryRunner : public velox::exec::test::ReferenceQueryRunner {
public:
/// @param coordinatorUri Presto REST API endpoint, e.g. http://127.0.0.1:8080
Expand Down Expand Up @@ -99,6 +104,10 @@ class PrestoQueryRunner : public velox::exec::test::ReferenceQueryRunner {
const std::vector<RowVectorPtr>& buildInput,
const RowTypePtr& resultType) override;

std::shared_ptr<QueryRunnerContext> queryRunnerContext() {
return queryRunnerContext_;
}

private:
memory::MemoryPool* pool() {
return pool_.get();
Expand Down Expand Up @@ -141,6 +150,7 @@ class PrestoQueryRunner : public velox::exec::test::ReferenceQueryRunner {
const std::chrono::milliseconds timeout_;
folly::EventBaseThread eventBaseThread_{false};
std::shared_ptr<memory::MemoryPool> pool_;
std::shared_ptr<QueryRunnerContext> queryRunnerContext_;
};

} // namespace facebook::velox::exec::test
Loading
Loading