```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".

pipes.emplace_back(std::move(ordinary_pipe));
    auto pipe = Pipe::unitePipes(std::move(pipes));
    
    pipe.resize(1);
    auto step = std::make_unique<ReadFromStorageStep>(std::move(pipe), "MergeTree(with projection)");
    auto plan = std::make_unique<QueryPlan>();
    plan->addStep(std::move(step));
    return plan;
}
QueryPlanPtr MergeTreeDataSelectExecutor::readFromParts(
    MergeTreeData::DataPartsVector parts,
    const Names & column_names_to_return,
    const StorageMetadataPtr & metadata_snapshot_base,
    const StorageMetadataPtr & metadata_snapshot,
    const SelectQueryInfo & query_info,
    ContextPtr context,
    const UInt64 max_block_size,
    const unsigned num_streams,
    const PartitionIdToMaxBlock * max_block_numbers_to_read,
    MergeTreeDataSelectCache * cache) const
{
    bool use_cache = cache && cache->use_cache;
    
    
    Names virt_column_names;
    Names real_column_names;
    size_t total_parts = parts.size();
    if (!use_cache && total_parts == 0)
        return std::make_unique<QueryPlan>();
    bool sample_factor_column_queried = false;