| 1864 | } |
| 1865 | |
| 1866 | void tryOutfile(BlockIO & streams, ASTPtr ast, ContextMutablePtr context) |
| 1867 | { |
| 1868 | const ASTQueryWithOutput * ast_query_with_output = dynamic_cast<const ASTQueryWithOutput *>(ast.get()); |
| 1869 | |
| 1870 | if (ast_query_with_output == nullptr || ast_query_with_output->out_file == nullptr |
| 1871 | || !OutfileTarget::checkOutfileWithTcpOnServer(context)) |
| 1872 | { |
| 1873 | return; |
| 1874 | } |
| 1875 | |
| 1876 | try |
| 1877 | { |
| 1878 | String format_name = ast_query_with_output && (ast_query_with_output->format != nullptr) |
| 1879 | ? getIdentifierName(ast_query_with_output->format) |
| 1880 | : context->getDefaultFormat(); |
| 1881 | |
| 1882 | String compression_method_str; |
| 1883 | UInt64 compression_level = 1; |
| 1884 | OutfileTarget::setOutfileCompression(ast_query_with_output, compression_method_str, compression_level); |
| 1885 | |
| 1886 | const auto & out_path = typeid_cast<const ASTLiteral &>(*ast_query_with_output->out_file).value.safeGet<std::string>(); |
| 1887 | OutfileTargetPtr outfile_target = std::make_shared<OutfileTarget>(context, out_path, format_name, compression_method_str, compression_level); |
| 1888 | std::shared_ptr<WriteBuffer> out_buf = outfile_target->getOutfileBuffer(); |
| 1889 | |
| 1890 | auto & pipeline = streams.pipeline; |
| 1891 | |
| 1892 | if (streams.in) |
| 1893 | { |
| 1894 | BlockOutputStreamPtr out = FormatFactory::instance().getOutputStreamParallelIfPossible( |
| 1895 | format_name, *out_buf, streams.in->getHeader(), context, {}); |
| 1896 | |
| 1897 | copyData( |
| 1898 | *streams.in, *out, []() { return false; }, [&out](const Block &) { out->flush(); }); |
| 1899 | } |
| 1900 | else if (pipeline.initialized()) |
| 1901 | { |
| 1902 | if (!pipeline.isCompleted()) |
| 1903 | { |
| 1904 | pipeline.addSimpleTransform([](const Block & header) { return std::make_shared<MaterializingTransform>(header); }); |
| 1905 | |
| 1906 | OutputFormatPtr out = FormatFactory::instance().getOutputFormatParallelIfPossible( |
| 1907 | format_name, *out_buf, pipeline.getHeader(), context, outfile_target->outToMultiFile(), {}); |
| 1908 | out->setOutFileTarget(outfile_target); |
| 1909 | |
| 1910 | out->setAutoFlush(); |
| 1911 | /// Save previous progress callback if any. |
| 1912 | auto previous_progress_callback = context->getProgressCallback(); |
| 1913 | |
| 1914 | /// NOTE Progress callback takes shared ownership of 'out'. |
| 1915 | pipeline.setProgressCallback([out, previous_progress_callback](const Progress & progress) { |
| 1916 | if (previous_progress_callback) |
| 1917 | previous_progress_callback(progress); |
| 1918 | out->onProgress(progress); |
| 1919 | }); |
| 1920 | |
| 1921 | pipeline.setOutputFormat(std::move(out)); |
| 1922 | } |
| 1923 | else |
no test coverage detected