void BinaryRowOutputStream::writePrefix() { size_t columns = sample.columns(); if (with_names || with_types) { writeVarUInt(columns, ostr); } if (with_names) { for (size_t i = 0; i < columns; ++i) { writeStringBinary(sample.safeGetByPosition(i).name, ostr); } } if (with_types) { for (size_t i = 0; i < columns; ++i) { writeStringBinary(sample.safeGetByPosition(i).type->getName(), ostr); } } }
void NativeBlockOutputStream::write(const Block & block) { /// Additional information about the block. if (client_revision >= DBMS_MIN_REVISION_WITH_BLOCK_INFO) block.info.write(ostr); /// Dimensions size_t columns = block.columns(); size_t rows = block.rows(); writeVarUInt(columns, ostr); writeVarUInt(rows, ostr); /** The index has the same structure as the data stream. * But instead of column values, it contains a mark that points to the location in the data file where this part of the column is located. */ if (index_ostr) { writeVarUInt(columns, *index_ostr); writeVarUInt(rows, *index_ostr); } for (size_t i = 0; i < columns; ++i) { /// For the index. MarkInCompressedFile mark; if (index_ostr) { ostr_concrete->next(); /// Finish compressed block. mark.offset_in_compressed_file = initial_size_of_file + ostr_concrete->getCompressedBytes(); mark.offset_in_decompressed_block = ostr_concrete->getRemainingBytes(); } const ColumnWithTypeAndName & column = block.safeGetByPosition(i); /// Name writeStringBinary(column.name, ostr); /// Type writeStringBinary(column.type->getName(), ostr); /// Data if (rows) /// Zero items of data is always represented as zero number of bytes. writeData(*column.type, column.column, ostr, 0, 0); if (index_ostr) { writeStringBinary(column.name, *index_ostr); writeStringBinary(column.type->getName(), *index_ostr); writeBinary(mark.offset_in_compressed_file, *index_ostr); writeBinary(mark.offset_in_decompressed_block, *index_ostr); } } }
void DistributedBlockOutputStream::writeToShard(const Block & block, const std::vector<std::string> & dir_names) { /** tmp directory is used to ensure atomicity of transactions * and keep monitor thread out from reading incomplete data */ std::string first_file_tmp_path{}; auto first = true; const auto & query_string = queryToString(query_ast); /// write first file, hardlink the others for (const auto & dir_name : dir_names) { const auto & path = storage.getPath() + dir_name + '/'; /// ensure shard subdirectory creation and notify storage if (Poco::File(path).createDirectory()) storage.requireDirectoryMonitor(dir_name); const auto & file_name = toString(storage.file_names_increment.get()) + ".bin"; const auto & block_file_path = path + file_name; /** on first iteration write block to a temporary directory for subsequent hardlinking to ensure * the inode is not freed until we're done */ if (first) { first = false; const auto & tmp_path = path + "tmp/"; Poco::File(tmp_path).createDirectory(); const auto & block_file_tmp_path = tmp_path + file_name; first_file_tmp_path = block_file_tmp_path; WriteBufferFromFile out{block_file_tmp_path}; CompressedWriteBuffer compress{out}; NativeBlockOutputStream stream{compress, ClickHouseRevision::get()}; writeStringBinary(query_string, out); stream.writePrefix(); stream.write(block); stream.writeSuffix(); } if (link(first_file_tmp_path.data(), block_file_path.data())) throwFromErrno("Could not link " + block_file_path + " to " + first_file_tmp_path); } /** remove the temporary file, enabling the OS to reclaim inode after all threads * have removed their corresponding files */ Poco::File(first_file_tmp_path).remove(); }
/// Записать изменённые настройки в буфер. (Например, для отправки на удалённый сервер.) void Settings::serialize(WriteBuffer & buf) const { #define WRITE(TYPE, NAME, DEFAULT) \ if (NAME.changed) \ { \ writeStringBinary(#NAME, buf); \ NAME.write(buf); \ } APPLY_FOR_SETTINGS(WRITE) limits.serialize(buf); /// Пустая строка - это маркер конца настроек. writeStringBinary("", buf); #undef WRITE }
void NativeBlockOutputStream::write(const Block & block) { /// Additional information about the block. if (client_revision > 0) block.info.write(ostr); block.checkNumberOfRows(); /// Dimensions size_t columns = block.columns(); size_t rows = block.rows(); writeVarUInt(columns, ostr); writeVarUInt(rows, ostr); /** The index has the same structure as the data stream. * But instead of column values, it contains a mark that points to the location in the data file where this part of the column is located. */ if (index_ostr) { writeVarUInt(columns, *index_ostr); writeVarUInt(rows, *index_ostr); } for (size_t i = 0; i < columns; ++i) { /// For the index. MarkInCompressedFile mark; if (index_ostr) { ostr_concrete->next(); /// Finish compressed block. mark.offset_in_compressed_file = initial_size_of_file + ostr_concrete->getCompressedBytes(); mark.offset_in_decompressed_block = ostr_concrete->getRemainingBytes(); } ColumnWithTypeAndName column = block.safeGetByPosition(i); /// Send data to old clients without low cardinality type. if (remove_low_cardinality || (client_revision && client_revision < DBMS_MIN_REVISION_WITH_LOW_CARDINALITY_TYPE)) { column.column = recursiveRemoveLowCardinality(column.column); column.type = recursiveRemoveLowCardinality(column.type); } /// Name writeStringBinary(column.name, ostr); /// Type String type_name = column.type->getName(); /// For compatibility, we will not send explicit timezone parameter in DateTime data type /// to older clients, that cannot understand it. if (client_revision < DBMS_MIN_REVISION_WITH_TIME_ZONE_PARAMETER_IN_DATETIME_DATA_TYPE && startsWith(type_name, "DateTime(")) type_name = "DateTime"; writeStringBinary(type_name, ostr); /// Data if (rows) /// Zero items of data is always represented as zero number of bytes. writeData(*column.type, column.column, ostr, 0, 0); if (index_ostr) { writeStringBinary(column.name, *index_ostr); writeStringBinary(column.type->getName(), *index_ostr); writeBinary(mark.offset_in_compressed_file, *index_ostr); writeBinary(mark.offset_in_decompressed_block, *index_ostr); } } }
void ODBCHandler::handleRequest(Poco::Net::HTTPServerRequest & request, Poco::Net::HTTPServerResponse & response) { Poco::Net::HTMLForm params(request, request.stream()); LOG_TRACE(log, "Request URI: " + request.getURI()); auto process_error = [&response, this](const std::string & message) { response.setStatusAndReason(Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); if (!response.sent()) response.send() << message << std::endl; LOG_WARNING(log, message); }; if (!params.has("query")) { process_error("No 'query' in request body"); return; } if (!params.has("columns")) { process_error("No 'columns' in request URL"); return; } if (!params.has("connection_string")) { process_error("No 'connection_string' in request URL"); return; } UInt64 max_block_size = DEFAULT_BLOCK_SIZE; if (params.has("max_block_size")) { std::string max_block_size_str = params.get("max_block_size", ""); if (max_block_size_str.empty()) { process_error("Empty max_block_size specified"); return; } max_block_size = parse<size_t>(max_block_size_str); } std::string columns = params.get("columns"); std::unique_ptr<Block> sample_block; try { sample_block = parseColumns(std::move(columns)); } catch (const Exception & ex) { process_error("Invalid 'columns' parameter in request body '" + ex.message() + "'"); LOG_WARNING(log, ex.getStackTrace().toString()); return; } std::string format = params.get("format", "RowBinary"); std::string query = params.get("query"); LOG_TRACE(log, "Query: " << query); std::string connection_string = params.get("connection_string"); LOG_TRACE(log, "Connection string: '" << connection_string << "'"); WriteBufferFromHTTPServerResponse out(request, response, keep_alive_timeout); try { BlockOutputStreamPtr writer = FormatFactory::instance().getOutput(format, out, *sample_block, *context); auto pool = getPool(connection_string); ODBCBlockInputStream inp(pool->get(), query, *sample_block, max_block_size); copyData(inp, *writer); } catch (...) { auto message = getCurrentExceptionMessage(true); response.setStatusAndReason( Poco::Net::HTTPResponse::HTTP_INTERNAL_SERVER_ERROR); // can't call process_error, bacause of too soon response sending writeStringBinary(message, out); tryLogCurrentException(log); } }