If they are defined, they can override table-level settings.
hardlinked_files->source_table_shared_id = src_part->storage.getTableSharedID();
        for (auto it = disk->iterateDirectory(src_part_path); it->isValid(); it->next())
        {
            if (it->name() != IMergeTreeDataPart::DELETE_ON_DESTROY_MARKER_FILE_NAME && it->name() != IMergeTreeDataPart::TXN_VERSION_METADATA_FILE_NAME)
                hardlinked_files->hardlinks_from_source_part.insert(it->name());
        }
    }
    /
    TransactionID tid = txn ? txn->tid : Tx::PrehistoricTID;
    dst_data_part->version.setCreationTID(tid, nullptr);
    dst_data_part->storeVersionMetadata();
    dst_data_part->is_temp = true;
    dst_data_part->loadColumnsChecksumsIndexes(require_part_metadata, true);
    dst_data_part->modification_time = disk->getLastModified(dst_part_path).epochTime();
    return dst_data_part;
}
String MergeTreeData::getFullPathOnDisk(const DiskPtr & disk) const
{
    return disk->getPath() + relative_data_path;
}
DiskPtr MergeTreeData::tryGetDiskForDetachedPart(const String & part_name) const
{
    String additional_path = "detached/";
    const auto disks = getStoragePolicy()->getDisks();
    for (const DiskPtr & disk : disks)
        if (disk->exists(relative_data_path + additional_path + part_name))
            return disk;
    return nullptr;
}
DiskPtr MergeTreeData::getDiskForDetachedPart(const String & part_name) const