**Use case**

This works:

```
SELECT * FROM hits_100m_obfuscated INTO OUTFILE 'hits.csv' FORMAT CSV
```

But I want this:

```
SELECT * FROM hits_100m_obfuscated INTO OUTFILE 'hits.csv'
```

**Describe the solution you'd like**

Every format can register file extension(s) in format factory.
If format is not specified explicitly, we can detect it automatically by file extension.
It should work for compressed files `hits.csv.gz` as well.

The following extensions should be supported at least:
csv, tsv, parquet, orc, native, json, ndjson, xml, md, avro

**Addition details**

Let's also support omitting the format argument for `file`, `url`, `s3`, `hdfs` table functions. 
data if we're fuzzing.
    if (block.rows() == 0 || (query_fuzzer_runs != 0 && processed_rows >= 100))
        return;
    /// If results are written INTO OUTFILE, we can avoid clearing progress to avoid flicker.
    if (need_render_progress && (stdout_is_a_tty || is_interactive) && !select_into_file)
        progress_indication.clearProgressOutput(
    output_format->write(materializeBlock(block)
    written_first_block = true;
    /// Received data block is immediately displayed to the user.
    output_format->flush(
    /// Restore progress bar after data block.
    if (need_render_progress && (stdout_is_a_tty || is_interactive))
    {
        if (select_into_file)
            std::cerr << "\r";
        progress_indication.writeProgress(
    }
}
void ClientBase::onLogData(Block & block)
{
    initLogsOutputStream(
    progress_indication.clearProgressOutput(
    logs_out_stream->writeLogs(block
    logs_out_stream->flush(
}
void ClientBase::onTotals(Block & block, ASTPtr parsed_query)
{
    initBlockOutputStream(block, parsed_query
    output_format->setTotals(block
}