For example Null can be represented as empty string

```sql
select arrayStringConcat(['x',Null], ';');

┌─arrayStringConcat(['x', Null], ';')─┐
│ x;                                  │
└─────────────────────────────────────┘
```

But mostly it for avoiding a cast in case of Nullable Strings
```
SELECT arrayStringConcat(col0, ';')
FROM
(
    SELECT [toNullable('x')] AS col0
) AS t
```

Also I think arrayStringConcat can support any types not only Strings, it allows to avoid explicit casts.

```
SELECT arrayStringConcat(col0, ';')
FROM
(
    SELECT [1, 2, 3] AS col0
) AS t
```
const ColumnString & col_string,
        const ColumnArray & col_arr,
        const String & delimiter,
        ColumnString & col_res,
        const char8_t * null_map = nullptr)
    {
        executeInternal(
            col_string.getChars(),
            col_string.getOffsets(),
            col_arr.getOffsets(),
            delimiter.data(),
            delimiter.size(),
            col_res.getChars(),
            col_res.getOffsets(),
            null_map);
    }
public:
    static constexpr auto name = "arrayStringConcat";
    static FunctionPtr create(ContextPtr) { return std::make_shared<FunctionArrayStringConcat>(); }
    String getName() const override
    {
        return name;
    }
    bool isVariadic() const override { return true; }