Repository: duckdb/duckdb
File: src/storage/table/row_version_manager.cpp (C++)

Code before:
		// info exists but it's a constant info: convert to a vector info
		auto new_info = make_uniq<ChunkVectorInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
		new_info->insert_id = constant.insert_id;
		for (idx_t i = 0; i < STANDARD_VECTOR_SIZE; i++) {
			new_info->inserted[i] = constant.insert_id;
		}
		vector_info[vector_idx] = std::move(new_info);
	}
	D_ASSERT(vector_info[vector_idx]->type == ChunkInfoType::VECTOR_INFO);
	return vector_info[vector_idx]->Cast<ChunkVectorInfo>();
}

idx_t RowVersionManager::DeleteRows(idx_t vector_idx, transaction_t transaction_id, row_t rows[], idx_t count) {
	lock_guard<mutex> lock(version_lock);
	has_changes = true;
	return GetVectorInfo(vector_idx).Delete(transaction_id, rows, count);
}

void RowVersionManager::CommitDelete(idx_t vector_idx, transaction_t commit_id, const DeleteInfo &info) {
	lock_guard<mutex> lock(version_lock);
	has_changes = true;
	GetVectorInfo(vector_idx).CommitDelete(commit_id, info);
}

vector<MetaBlockPointer> RowVersionManager::Checkpoint(MetadataManager &manager) {
	if (!has_changes) {
		// we can write the current pointer as-is
		// ensure the blocks we are pointing to are not marked as free
		manager.ClearModifiedBlocks(storage_pointers);
		// return the current set of pointers
		return storage_pointers;
	}
	// first count how many ChunkInfo's we need to deserialize
	vector<pair<idx_t, reference<ChunkInfo>>> to_serialize;
	for (idx_t vector_idx = 0; vector_idx < vector_info.size(); vector_idx++) {
		auto chunk_info = vector_info[vector_idx].get();
		if (!chunk_info) {
			continue;
		}
		if (!chunk_info->HasDeletes()) {
			continue;
		}
		to_serialize.emplace_back(vector_idx, *chunk_info);
	}

	storage_pointers.clear();

	if (!to_serialize.empty()) {
		MetadataWriter writer(manager, &storage_pointers);
		// now serialize the actual version information
		writer.Write<idx_t>(to_serialize.size());

Review comment (suggestion):
I don't think it's necessary yet given the aggressive locking we have around checkpointing elsewhere - but this should probably grab the `version_lock` as well 

Code after:
		auto &constant = vector_info[vector_idx]->Cast<ChunkConstantInfo>();
		// info exists but it's a constant info: convert to a vector info
		auto new_info = make_uniq<ChunkVectorInfo>(start + vector_idx * STANDARD_VECTOR_SIZE);
		new_info->insert_id = constant.insert_id;
		for (idx_t i = 0; i < STANDARD_VECTOR_SIZE; i++) {
			new_info->inserted[i] = constant.insert_id;
		}
		vector_info[vector_idx] = std::move(new_info);
	}
	D_ASSERT(vector_info[vector_idx]->type == ChunkInfoType::VECTOR_INFO);
	return vector_info[vector_idx]->Cast<ChunkVectorInfo>();
}

idx_t RowVersionManager::DeleteRows(idx_t vector_idx, transaction_t transaction_id, row_t rows[], idx_t count) {
	lock_guard<mutex> lock(version_lock);
	has_unserialized_changes = true;
	return GetVectorInfo(vector_idx).Delete(transaction_id, rows, count);
}

void RowVersionManager::CommitDelete(idx_t vector_idx, transaction_t commit_id, const DeleteInfo &info) {
	lock_guard<mutex> lock(version_lock);
	has_unserialized_changes = true;
	GetVectorInfo(vector_idx).CommitDelete(commit_id, info);
}

vector<MetaBlockPointer> RowVersionManager::Checkpoint(MetadataManager &manager) {
	lock_guard<mutex> lock(version_lock);
	if (!has_unserialized_changes) {
		// we can write the current pointer as-is
		// ensure the blocks we are pointing to are not marked as free
		manager.ClearModifiedBlocks(storage_pointers);
		// return the current set of pointers
		return storage_pointers;
	}
	// first count how many ChunkInfo's we need to deserialize
	vector<pair<idx_t, reference<ChunkInfo>>> to_serialize;
	for (idx_t vector_idx = 0; vector_idx < vector_info.size(); vector_idx++) {
		auto chunk_info = vector_info[vector_idx].get();
		if (!chunk_info) {
			continue;
		}
		if (!chunk_info->HasDeletes()) {
			continue;
		}
		to_serialize.emplace_back(vector_idx, *chunk_info);
	}

	storage_pointers.clear();

	if (!to_serialize.empty()) {
		MetadataWriter writer(manager, &storage_pointers);