**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. 
SCOPE_EXIT_SAFE({
            if (old_settings)
                global_context->setSettings(*old_settings
        }
        auto apply_query_settings = [&](const IAST & settings_ast)
        {
            if (!old_settings)
                old_settings.emplace(global_context->getSettingsRef()
            global_context->applySettingsChanges(settings_ast.as<ASTSetQuery>()->changes
        };
        const auto * insert = parsed_query->as<ASTInsertQuery>(
        if (insert && insert->settings_ast)
            apply_query_settings(*insert->settings_ast
        /// FIXME: try to prettify this cast using `as<>()`
        const auto * with_output = dynamic_cast<const ASTQueryWithOutput *>(parsed_query.get()
        if (with_output && with_output->settings_ast)
            apply_query_settings(*with_output->settings_ast
        if (!connection->checkConnected())
            connect(
        ASTPtr input_function;
        if (insert && insert->select)
            insert->tryFindInputFunction(input_function
        /// INSERT query for which data transfer is needed (not an INSERT SELECT or input()) is processed separately.
        if (insert && (!insert->select || input_function) && !insert->watch)
        {
            if (input_function && insert->format.empty())
                throw Exception("FORMAT must be specified for function input()", ErrorCodes::INVALID_USAGE_OF_INPUT
            processInsertQuery(query_to_execute, parsed_query
        }
        else