ResultType TrafficCop::ExecuteStatement( const std::string &query, std::vector<StatementResult> &result, std::vector<FieldInfo> &tuple_descriptor, int &rows_changed, std::string &error_message, const size_t thread_id UNUSED_ATTRIBUTE) { LOG_TRACE("Received %s", query.c_str()); // Prepare the statement std::string unnamed_statement = "unnamed"; auto statement = PrepareStatement(unnamed_statement, query, error_message); if (statement.get() == nullptr) { return ResultType::FAILURE; } // Then, execute the statement bool unnamed = true; std::vector<int> result_format(statement->GetTupleDescriptor().size(), 0); std::vector<type::Value> params; auto status = ExecuteStatement(statement, params, unnamed, nullptr, result_format, result, rows_changed, error_message, thread_id); if (status == ResultType::SUCCESS) { LOG_TRACE("Execution succeeded!"); tuple_descriptor = std::move(statement->GetTupleDescriptor()); } else { LOG_TRACE("Execution failed!"); } return status; }
void StatsTestsUtil::ShowTable(std::string database_name, std::string table_name) { catalog::Catalog::GetInstance()->GetTableWithName(database_name, table_name); std::unique_ptr<Statement> statement; auto &peloton_parser = parser::Parser::GetInstance(); std::vector<common::Value> params; std::vector<ResultType> result; std::string sql = "SELECT * FROM " + database_name + "." + table_name; statement.reset(new Statement("SELECT", sql)); auto select_stmt = peloton_parser.BuildParseTree(sql); statement->SetPlanTree( optimizer::SimpleOptimizer::BuildPelotonPlanTree(select_stmt)); bridge::PlanExecutor::PrintPlan(statement->GetPlanTree().get(), "Plan"); std::vector<int> result_format(statement->GetTupleDescriptor().size(), 0); bridge::PlanExecutor::ExecutePlan(statement->GetPlanTree().get(), params, result, result_format); }
// The Simple Query Protocol // Fix mis-split bug: Previously, this function assumes there are multiple // queries in the string and split it by ';', which would cause one containing // ';' being split into multiple queries. // However, the multi-statement queries has been split by the psql client and // there is no need to split the query again. void PacketManager::ExecQueryMessage(InputPacket *pkt, const size_t thread_id) { std::string query; PacketGetString(pkt, pkt->len, query); // pop out the last character if it is ';' if (query.back() == ';') { query.pop_back(); } boost::trim(query); if (!query.empty()) { std::vector<StatementResult> result; std::vector<FieldInfo> tuple_descriptor; std::string error_message; int rows_affected = 0; std::string query_type_string_; Statement::ParseQueryTypeString(query, query_type_string_); QueryType query_type; Statement::MapToQueryType(query_type_string_, query_type); std::stringstream stream(query_type_string_); switch (query_type) { case QueryType::QUERY_PREPARE: { std::string statement_name; stream >> statement_name; std::size_t pos = query.find("AS"); std::string statement_query = query.substr(pos + 3); boost::trim(statement_query); // Prepare statement std::shared_ptr<Statement> statement(nullptr); LOG_DEBUG("PrepareStatement[%s] => %s", statement_name.c_str(), statement_query.c_str()); statement = traffic_cop_->PrepareStatement(statement_name, statement_query, error_message); if (statement.get() == nullptr) { skipped_stmt_ = true; SendErrorResponse( {{NetworkMessageType::HUMAN_READABLE_ERROR, error_message}}); LOG_TRACE("ExecQuery Error"); return; } auto entry = std::make_pair(statement_name, statement); statement_cache_.insert(entry); for (auto table_id : statement->GetReferencedTables()) { table_statement_cache_[table_id].push_back(statement.get()); } break; } case QueryType::QUERY_EXECUTE: { std::string statement_name; std::shared_ptr<Statement> statement; std::vector<type::Value> param_values; bool unnamed = false; std::vector<std::string> tokens; boost::split(tokens, query, boost::is_any_of("(), ")); statement_name = tokens.at(1); auto statement_cache_itr = statement_cache_.find(statement_name); if (statement_cache_itr != statement_cache_.end()) { statement = *statement_cache_itr; } // Did not find statement with same name else { std::string error_message = "The prepared statement does not exist"; LOG_ERROR("%s", error_message.c_str()); SendErrorResponse( {{NetworkMessageType::HUMAN_READABLE_ERROR, error_message}}); SendReadyForQuery(NetworkTransactionStateType::IDLE); return; } std::vector<int> result_format(statement->GetTupleDescriptor().size(), 0); for (std::size_t idx = 2; idx < tokens.size(); idx++) { std::string param_str = tokens.at(idx); boost::trim(param_str); if (param_str.empty()) { continue; } param_values.push_back(type::ValueFactory::GetVarcharValue(param_str)); } if (param_values.size() > 0) { statement->GetPlanTree()->SetParameterValues(¶m_values); } auto status = traffic_cop_->ExecuteStatement(statement, param_values, unnamed, nullptr, result_format, result, rows_affected, error_message, thread_id); if (status == ResultType::SUCCESS) { tuple_descriptor = statement->GetTupleDescriptor(); } else { SendErrorResponse( {{NetworkMessageType::HUMAN_READABLE_ERROR, error_message}}); SendReadyForQuery(NetworkTransactionStateType::IDLE); return; } break; } default: { // execute the query using tcop auto status = traffic_cop_->ExecuteStatement( query, result, tuple_descriptor, rows_affected, error_message, thread_id); // check status if (status == ResultType::FAILURE) { SendErrorResponse( {{NetworkMessageType::HUMAN_READABLE_ERROR, error_message}}); SendReadyForQuery(NetworkTransactionStateType::IDLE); return; } } } // send the attribute names PutTupleDescriptor(tuple_descriptor); // send the result rows SendDataRows(result, tuple_descriptor.size(), rows_affected); // The response to the SimpleQueryCommand is the query string. CompleteCommand(query, query_type, rows_affected); } else {
/** * @return true on success, false otherwise. */ bool CopyExecutor::DExecute() { // skip if we're done if (done) { return false; } while (children_[0]->Execute() == true) { // Get input a tile std::unique_ptr<LogicalTile> logical_tile(children_[0]->GetOutput()); LOG_DEBUG("Looping over the output tile.."); // Get physical schema of the tile std::unique_ptr<catalog::Schema> output_schema( logical_tile->GetPhysicalSchema()); // vectors for prepared statement parameters int num_params = 0; std::vector<std::pair<type::TypeId, std::string>> bind_parameters; std::vector<type::Value> param_values; std::vector<int16_t> formats; std::vector<int32_t> types; // Construct result format as varchar auto col_count = output_schema->GetColumnCount(); std::vector<std::vector<std::string>> answer_tuples; std::vector<int> result_format(col_count, 0); answer_tuples = logical_tile->GetAllValuesAsStrings(result_format, true); // Loop over the returned results for (auto &tuple : answer_tuples) { // Loop over the columns for (unsigned int col_index = 0; col_index < col_count; col_index++) { auto val = tuple[col_index]; auto origin_col_id = logical_tile->GetColumnInfo(col_index).origin_column_id; int len = val.length(); if (origin_col_id == num_param_col_id) { // num_param column num_params = std::stoi(val); Copy(val.c_str(), val.length(), false); } else if (origin_col_id == param_type_col_id) { // param_types column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); // Read param types types.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamType(&packet, num_params, types); // Write all the types to output file for (int i = 0; i < num_params; i++) { std::string type_str = std::to_string(types[i]); Copy(type_str.c_str(), type_str.length(), false); } } else if (origin_col_id == param_format_col_id) { // param_formats column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); // Read param formats formats.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamFormat(&packet, num_params, formats); } else if (origin_col_id == param_val_col_id) { // param_values column PELOTON_ASSERT(output_schema->GetColumn(col_index).GetType() == type::TypeId::VARBINARY); network::InputPacket packet(len, val); bind_parameters.resize(num_params); param_values.resize(num_params); //TODO: Instead of passing packet to executor, some data structure more generic is need network::PostgresProtocolHandler::ReadParamValue(&packet, num_params, types, bind_parameters, param_values, formats); // Write all the values to output file for (int i = 0; i < num_params; i++) { auto param_value = param_values[i]; LOG_TRACE("param_value.GetTypeId(): %s", TypeIdToString(param_value.GetTypeId()).c_str()); // Avoid extra copy for varlen types if (param_value.GetTypeId() == type::TypeId::VARBINARY) { const char *data = param_value.GetData(); Copy(data, param_value.GetLength(), false); } else if (param_value.GetTypeId() == type::TypeId::VARCHAR) { const char *data = param_value.GetData(); // Don't write the NULL character for varchar Copy(data, param_value.GetLength() - 1, false); } else { // Convert integer / double types to string before copying auto param_str = param_value.ToString(); Copy(param_str.c_str(), param_str.length(), false); } } } else { // For other columns, just copy the content to local buffer bool end_of_line = col_index == col_count - 1; Copy(val.c_str(), val.length(), end_of_line); } } } LOG_DEBUG("Done writing to csv file for this tile"); } LOG_INFO("Done copying all logical tiles"); FlushBuffer(); FFlushFsync(); // Sync and close fclose(file_handle_.file); done = true; return true; }