blob: cb8f153a8ed3b8e5e89468f72ed50d4c41463dbf [file] [log] [blame]
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 "query_optimizer/tests/OptimizerTextTestRunner.hpp"
#include <set>
#include <string>
#include <vector>
#include "query_optimizer/LogicalGenerator.hpp"
#include "query_optimizer/OptimizerContext.hpp"
#include "query_optimizer/PhysicalGenerator.hpp"
#include "query_optimizer/logical/Logical.hpp"
#include "query_optimizer/physical/Physical.hpp"
#include "query_optimizer/resolver/Resolver.hpp"
#include "utility/SqlError.hpp"
#include "glog/logging.h"
namespace quickstep {
namespace optimizer {
const std::vector<std::string> OptimizerTextTestRunner::kTestOptions = {
"initial_logical_plan", "optimized_logical_plan", "physical_plan"};
void OptimizerTextTestRunner::runTestCase(const std::string &input,
const std::set<std::string> &options,
std::string *output) {
CHECK(!options.empty()) << "No options specified";
VLOG(4) << "Test SQL: " << input;
sql_parser_.feedNextBuffer(new std::string(input));
ParseResult result = sql_parser_.getNextStatement();
OptimizerContext optimizer_context;
if (result.condition != ParseResult::kSuccess) {
*output = result.error_message;
} else {
// Number of options specified.
int num_options = 0;
std::ostringstream out_ss;
try {
logical::LogicalPtr initial_logical_plan;
logical::LogicalPtr optimized_logical_plan;
physical::PhysicalPtr physical_plan;
const bool output_initial_logical_plan =
(options.find(kTestOptions[0]) != options.end());
const bool output_optimized_logical_plan =
(options.find(kTestOptions[1]) != options.end());
const bool output_physical_plan =
(options.find(kTestOptions[2]) != options.end());
if (output_initial_logical_plan) {
initial_logical_plan =
resolveParseTree(*result.parsed_statement, &optimizer_context);
++num_options;
}
if (output_optimized_logical_plan || output_physical_plan) {
optimized_logical_plan =
generateLogicalPlan(*result.parsed_statement, &optimizer_context);
if (output_optimized_logical_plan) {
++num_options;
}
}
if (output_physical_plan) {
physical_plan =
generatePhysicalPlan(optimized_logical_plan, &optimizer_context);
++num_options;
}
if (output_initial_logical_plan) {
if (num_options > 1) {
out_ss << "[Initial Logical Plan]\n";
}
out_ss << initial_logical_plan->toString();
}
if (output_optimized_logical_plan) {
if (num_options > 1) {
out_ss << "[Optimized Logical Plan]\n";
}
out_ss << optimized_logical_plan->toString();
}
if (output_physical_plan) {
if (num_options > 1) {
out_ss << "[Physical Plan]\n";
}
out_ss << physical_plan->toString();
}
*output = out_ss.str();
CHECK(!output->empty());
} catch (const SqlError &error) {
*output = error.formatMessage(input);
}
}
}
logical::LogicalPtr OptimizerTextTestRunner::resolveParseTree(
const ParseStatement &parse_statement,
OptimizerContext *optimizer_context) {
resolver::Resolver resolver(*test_database_loader_.catalog_database(), optimizer_context);
return resolver.resolve(parse_statement);
}
logical::LogicalPtr OptimizerTextTestRunner::generateLogicalPlan(
const ParseStatement &parse_statement,
OptimizerContext *optimizer_context) {
LogicalGenerator logical_generator(optimizer_context);
return logical_generator.generatePlan(*test_database_loader_.catalog_database(),
parse_statement);
}
physical::PhysicalPtr OptimizerTextTestRunner::generatePhysicalPlan(
const logical::LogicalPtr &logical_plan,
OptimizerContext *optimizer_context) {
PhysicalGenerator physical_generator(optimizer_context);
return physical_generator.generatePlan(logical_plan);
}
} // namespace optimizer
} // namespace quickstep