**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. 
const auto & external_options = options_description.external_description->options(
        std::transform(external_options.begin(), external_options.end(), std::back_inserter(cmd_options), getter
    }
    parseAndCheckOptions(options_description, options, common_arguments
    po::notify(options
    if (options.count("version") || options.count("V"))
    {
        showClientVersion(
        exit(0
    }
    if (options.count("version-clean"))
    {
        std::cout << VERSION_STRING;
        exit(0
    }
    /// Output of help message.
    if (options.count("help")
        || (options.count("host") && options["host"].as<std::string>() == "elp")) /// If user writes -help instead of --help.
    {
        printHelpMessage(options_description
        exit(0
    }
    /// Common options for clickhouse-client and clickhouse-local.
    if (options.count("time"))
        print_time_to_stderr = true;
    if (options.count("query"))
        config().setString("query", options["query"].as<std::string>()
    if (options.count("query_id"))
        config().setString("query_id", options["query_id"].as<std::string>()
    if (options.count("database"))