Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Storages/StorageMaterializedView.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,14 @@ void StorageMaterializedView::read(
std::tie(storage, lock) = refresher->getAndLockTargetTable(getTargetTableId(), context);
}

/// For datalake target tables (e.g. IcebergLocal), we must refresh external metadata
/// before reading. Without this call the storage snapshot will lack the
/// datalake_table_state, causing a LOGICAL_ERROR in iterate().
/// Normally updateExternalDynamicMetadataIfExists is called by the analyzer/interpreter
/// on the outermost storage, but for materialized views that is the view itself
/// (which is a no-op), not the target table.
storage->updateExternalDynamicMetadataIfExists(context);

auto target_metadata_snapshot = storage->getInMemoryMetadataPtr();
auto target_storage_snapshot = storage->getStorageSnapshot(target_metadata_snapshot, context);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
42
OK
40 changes: 40 additions & 0 deletions tests/queries/0_stateless/04077_iceberg_mv_select_crash.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#!/usr/bin/env bash
# Tags: no-fasttest, no-replicated-database
# Tag no-replicated-database: IcebergLocal is non-replicated; REFRESH MV + replicated database + non-replicated target is rejected.

# Regression test for https://github.com/ClickHouse/ClickHouse/issues/93278
# SELECT from a materialized view backed by IcebergLocal engine used to crash
# with "Logical error: Can't extract iceberg table state from storage snapshot".
# The root cause: StorageMaterializedView::read() delegates to the target table
# without calling updateExternalDynamicMetadataIfExists(), so the storage
# snapshot lacks datalake_table_state when IcebergMetadata::iterate() is called.

CURDIR=$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)
# shellcheck source=../shell_config.sh
. "$CURDIR"/../shell_config.sh

TABLE="t_${CLICKHOUSE_DATABASE}_${RANDOM}"
TABLE_PATH="${USER_FILES_PATH}/${TABLE}/"

${CLICKHOUSE_CLIENT} --query "DROP VIEW IF EXISTS ${TABLE}_mv"

# Create a materialized view with IcebergLocal target.
${CLICKHOUSE_CLIENT} --query "
CREATE MATERIALIZED VIEW ${TABLE}_mv
REFRESH AFTER 1 MINUTE
ENGINE = IcebergLocal('${TABLE_PATH}')
AS (SELECT 1::Int32 AS c0)
"

# This used to crash the server with LOGICAL_ERROR.
${CLICKHOUSE_CLIENT} --query "SELECT * FROM ${TABLE}_mv"

# Insert data and verify it's readable through the view.
${CLICKHOUSE_CLIENT} --query "INSERT INTO ${TABLE}_mv VALUES (42)" --allow_insert_into_iceberg 1
${CLICKHOUSE_CLIENT} --query "SELECT c0 FROM ${TABLE}_mv"

# Clean up.
${CLICKHOUSE_CLIENT} --query "DROP VIEW IF EXISTS ${TABLE}_mv"
rm -rf "${TABLE_PATH}" 2>/dev/null

echo "OK"
Loading