**Use case**

#18842 

**Describe the solution you'd like**

`SELECT file('nonexisting')` - throws exception;
`SELECT file('nonexisting', '')` - returns empty string;
`SELECT file('nonexisting', NULL)` - returns NULL.

{
public:
    static constexpr auto name = "file";
    static FunctionPtr create(ContextPtr context_) { return std::make_shared<FunctionFile>(context_); }
    explicit FunctionFile(ContextPtr context_) : WithContext(context_) {}
    String getName() const override { return name; }
    size_t getNumberOfArguments() const override { return 1; }
    bool isSuitableForShortCircuitArgumentsExecution(const DataTypesWithConstInfo & ) const override { return true; }
    DataTypePtr getReturnTypeImpl(const ColumnsWithTypeAndName & arguments) const override
    {
        if (!isString(arguments[0].type))
            throw Exception(ErrorCodes::NOT_IMPLEMENTED, "{} is only implemented for type String", getName());
        return std::make_shared<DataTypeString>();
    }
    bool useDefaultImplementationForConstants() const override { return true; }
    ColumnPtr executeImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr &, size_t input_rows_count) const override
    {
        const ColumnPtr column = arguments[0].column;
        const ColumnString * column_src = checkAndGetColumn<ColumnString>(column.get());
        if (!column_src)
            throw Exception(
                fmt::format("Illegal column {} of argument of function {}", arguments[0].column->getName(), getName()),
                ErrorCodes::ILLEGAL_COLUMN);
        auto result = ColumnString::create();
        auto & res_chars = result->getChars();
        auto & res_offsets = result->getOffsets();
        res_offsets.resize(input_rows_count);
        fs::path user_files_absolute_path = fs::canonical(fs::path(getContext()->getUserFilesPath()));