```
CREATE TABLE t (x UInt8, PROJECTION p (SELECT x GROUP BY x)) ENGINE = MergeTree ORDER BY ();
INSERT INTO t VALUES (0);

SET group_by_overflow_mode = 'any', max_rows_to_group_by = 1000, totals_mode = 'after_having_auto';
SELECT x FROM t GROUP BY x WITH TOTALS;
```
void MergeTreeData::restoreDataFromBackup(RestorerFromBackup & restorer, const String & data_path_in_backup, const std::optional<ASTs> & partitions)
{
    auto backup = restorer.getBackup();
    if (!backup->hasFiles(data_path_in_backup))
        return;
    if (!restorer.isNonEmptyTableAllowed() && getTotalActiveSizeInBytes() && backup->hasFiles(data_path_in_backup))
        restorer.throwTableIsNotEmpty(getStorageID());
    restorePartsFromBackup(restorer, data_path_in_backup, partitions);
}
class MergeTreeData::RestoredPartsHolder
{
public:
    RestoredPartsHolder(const std::shared_ptr<MergeTreeData> & storage_, const BackupPtr & backup_, size_t num_parts_)
        : storage(storage_), backup(backup_), num_parts(num_parts_)
    {
    }
    BackupPtr getBackup() const { return backup; }
    void setNumParts(size_t num_parts_)
    {
        std::lock_guard lock{mutex};
        num_parts = num_parts_;
        attachIfAllPartsRestored();
    }
    void addPart(MutableDataPartPtr part)
    {
        std::lock_guard lock{mutex};
        parts.emplace_back(part);
        attachIfAllPartsRestored();
    }
    String getTemporaryDirectory(const DiskPtr & disk)