Reproduction example:

```(sql)
SET join_use_nulls = 0;

create or replace view
  some_test_view
as
select *
from
  (
    select
      arrayJoin([1, 2]) as a,
      arrayJoin([11, 12]) as b
  ) as t1
  full join
  (
    select
      arrayJoin([2, 3]) as a,
      arrayJoin([22, 23]) as c
  ) as t2
  using a
order by a
```

In `describe table some_test_view` the resulting columns are non-nullable, as expected.

However, changing the setting and selecting from the view:

```(sql)
SET join_use_nulls = 1;
select * from some_test_view
```

Results in an error: `Code: 349, e.displayText() = DB::Exception: Cannot convert NULL value to non-Nullable type: while converting source column c to destination column c: while executing 'FUNCTION CAST(c :: 2, UInt8 :: 5) -> CAST(c, UInt8) UInt8 : 4' (version 21.2.3.15 (official build))`

There's no clearly-good solution to this problem;
one of the suggestions is to add the setting to the view schema, e.g.:

```(sql)
SET join_use_nulls = 0;

create or replace view
  some_test_view
as
select *
from
  (
    select
      arrayJoin([1, 2]) as a,
      arrayJoin([11, 12]) as b
  ) as t1
  full join
  (
    select
      arrayJoin([2, 3]) as a,
      arrayJoin([22, 23]) as c
  ) as t2
  using a
order by a
settings join_use_nulls = 0  -- prevent the join behavior inside the view from changing
```

which could be done implicitly by CH to improve the user experience.

Side note: `… settings join_use_nulls = …` seems to be poorly documented, only appearing in a few examples without any explanation.

}
    InterpreterSelectWithUnionQuery interpreter(current_inner_query, context, {}, column_names);
    interpreter.buildQueryPlan(query_plan);
    
    
    auto materializing_actions = std::make_shared<ActionsDAG>(query_plan.getCurrentDataStream().header.getColumnsWithTypeAndName());
    materializing_actions->addMaterializingOutputActions();
    auto materializing = std::make_unique<ExpressionStep>(query_plan.getCurrentDataStream(), std::move(materializing_actions));
    materializing->setStepDescription("Materialize constants after VIEW subquery");
    query_plan.addStep(std::move(materializing));
    
    auto header = metadata_snapshot->getSampleBlockForColumns(column_names, getVirtuals(), getStorageID());
    auto convert_actions_dag = ActionsDAG::makeConvertingActions(
            query_plan.getCurrentDataStream().header.getColumnsWithTypeAndName(),
            header.getColumnsWithTypeAndName(),
            ActionsDAG::MatchColumnsMode::Name);
    auto converting = std::make_unique<ExpressionStep>(query_plan.getCurrentDataStream(), convert_actions_dag);
    converting->setStepDescription("Convert VIEW subquery result to VIEW table structure");
    query_plan.addStep(std::move(converting));
}
static ASTTableExpression * getFirstTableExpression(ASTSelectQuery & select_query)
{
    if (!select_query.tables() || select_query.tables()->children.empty())
        throw Exception("Logical error: no table expression in view select AST", ErrorCodes::LOGICAL_ERROR);
    auto * select_element = select_query.tables()->children[0]->as<ASTTablesInSelectQueryElement>();
    if (!select_element->table_expression)
        throw Exception("Logical error: incorrect table expression", ErrorCodes::LOGICAL_ERROR);
    return select_element->table_expression->as<ASTTableExpression>();
}
void StorageView::replaceWithSubquery(ASTSelectQuery & outer_query, ASTPtr view_query, ASTPtr & view_name)