Repository: duckdb/duckdb
File: extension/parquet/parquet_file_metadata_cache.cpp (C++)

Code before:
      crypto_metadata(std::move(crypto_metadata)), footer_size(footer_size), validate(handle.Validate()),
      last_modified(handle.GetLastModifiedTime()), version_tag(handle.GetVersionTag()) {
}

string ParquetFileMetadataCache::ObjectType() {
	return "parquet_metadata";
}

string ParquetFileMetadataCache::GetObjectType() {
	return ObjectType();
}

idx_t ParquetFileMetadataCache::GetRoughCacheMemory() const {
	// Base memory consumption
	idx_t memory = sizeof(*this);

	if (metadata) {
		// Base overhead
		memory += 1024;
		// Estimate ~1KB per row group + column stats
		memory += metadata->row_groups.size() * 1024;
		// Column schema information
		memory += metadata->schema.size() * 256;
	}
	if (geo_metadata) {
		memory += 512;
	}

	if (crypto_metadata) {
		memory += 256;
	}

	memory += footer_size;
	memory += version_tag.size();

	return memory;
}

bool ParquetFileMetadataCache::IsValid(CachingFileHandle &new_handle) const {
	return ExternalFileCache::IsValid(validate, version_tag, last_modified, new_handle.GetVersionTag(),
	                                  new_handle.GetLastModifiedTime());
}

ParquetCacheValidity ParquetFileMetadataCache::IsValid(const OpenFileInfo &info) const {
	if (!info.extended_info) {
		return ParquetCacheValidity::UNKNOWN;
	}
	auto &open_options = info.extended_info->options;
	const auto validate_entry = open_options.find("validate_external_file_cache");
	if (validate_entry != open_options.end()) {
		// check if always valid - if so just return valid

Review comment (suggestion):
This should be a more accurate estimate:
```C++
sizeof(GeoParquetFileMetadata) + stats->GetColumnMeta().size() * sizeof(GeoParquetColumnMetadata);
```

Code after:
                                                   unique_ptr<FileCryptoMetaData> crypto_metadata, idx_t footer_size)
    : metadata(std::move(file_metadata)), geo_metadata(std::move(geo_metadata)),
      crypto_metadata(std::move(crypto_metadata)), footer_size(footer_size), validate(handle.Validate()),
      last_modified(handle.GetLastModifiedTime()), version_tag(handle.GetVersionTag()) {
}

string ParquetFileMetadataCache::ObjectType() {
	return "parquet_metadata";
}

string ParquetFileMetadataCache::GetObjectType() {
	return ObjectType();
}

optional_idx ParquetFileMetadataCache::GetEstimatedCacheMemory() const {
	// Base memory consumption
	idx_t memory = sizeof(*this);

	if (metadata) {
		const auto num_cols = metadata->schema.size();
		memory += sizeof(duckdb_parquet::FileMetaData);
		memory += num_cols * sizeof(duckdb_parquet::SchemaElement);
		memory += metadata->row_groups.size() * sizeof(duckdb_parquet::RowGroup) +
		          num_cols * sizeof(duckdb_parquet::ColumnChunk);
	}
	if (geo_metadata) {
		memory +=
		    sizeof(GeoParquetFileMetadata) + geo_metadata->GetColumnMeta().size() * sizeof(GeoParquetColumnMetadata);
	}
	if (crypto_metadata) {
		memory += sizeof(FileCryptoMetaData);
	}

	memory += footer_size;
	memory += version_tag.size();

	return memory;
}

bool ParquetFileMetadataCache::IsValid(CachingFileHandle &new_handle) const {
	return ExternalFileCache::IsValid(validate, version_tag, last_modified, new_handle.GetVersionTag(),
	                                  new_handle.GetLastModifiedTime());
}

ParquetCacheValidity ParquetFileMetadataCache::IsValid(const OpenFileInfo &info, ClientContext &context) const {
	CacheValidationMode validation_mode = ExternalFileCacheUtil::GetCacheValidationMode(info, &context, *context.db);
	if (validation_mode == CacheValidationMode::NO_VALIDATION) {
		return ParquetCacheValidity::VALID;
	}
	if (validation_mode == CacheValidationMode::VALIDATE_REMOTE && FileSystem::IsRemoteFile(info.path)) {
		return ParquetCacheValidity::VALID;