```sql
DROP TABLE IF EXISTS tp;

create table tp (d1 Int32, d2 Int32, eventcnt Int64,
projection p (select sum(eventcnt), d1 group by d1)) 
engine = SummingMergeTree order by (d1, d2);

set allow_experimental_projection_optimization = 1, force_optimize_projection = 1;

select sum(eventcnt) eventcnt, d1
from tp
group by d1;

DB::Exception: No projection is used when allow_experimental_projection_optimization = 1.

```

The exception message is also incorrect, should be "when force_optimize_projection = 1".

NamesAndTypesList available_real_columns = metadata_snapshot->getColumns().getAllPhysical();
    
    if (real_column_names.empty())
        real_column_names.push_back(ExpressionActions::getSmallestColumn(available_real_columns));
    metadata_snapshot->check(real_column_names, data.getVirtuals(), data.getStorageID());
    
    std::optional<KeyCondition> key_condition;
    if (!use_cache)
    {
        const auto & primary_key = metadata_snapshot->getPrimaryKey();
        Names primary_key_columns = primary_key.column_names;
        key_condition.emplace(query_info, context, primary_key_columns, primary_key.expression);
        if (settings.force_primary_key && key_condition->alwaysUnknownOrTrue())
        {
            throw Exception(
                ErrorCodes::INDEX_NOT_USED,
                "Primary key ({}) is not used and setting 'force_primary_key' is set.",
                fmt::join(primary_key_columns, ", "));
        }
        LOG_DEBUG(log, "Key condition: {}", key_condition->toString());
    }
    const auto & select = query_info.query->as<ASTSelectQuery &>();
    auto query_context = context->hasQueryContext() ? context->getQueryContext() : context;
    auto index_stats = use_cache ? std::move(cache->index_stats) : std::make_unique<ReadFromMergeTree::IndexStats>();
    
    if (!use_cache)
    {
        std::optional<PartitionPruner> partition_pruner;
        std::optional<KeyCondition> minmax_idx_condition;
        DataTypes minmax_columns_types;