Skip to content

Commit 04e1836

Browse files
committed
Add test showcasing session-scoped expression issues in MV refresh
1 parent 1008b94 commit 04e1836

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

plugin/trino-iceberg/src/test/java/io/trino/plugin/iceberg/BaseIcebergMaterializedViewTest.java

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import io.trino.spi.function.table.TableFunctionProcessorState;
4343
import io.trino.spi.function.table.TableFunctionSplitProcessor;
4444
import io.trino.spi.security.ConnectorIdentity;
45+
import io.trino.spi.security.Identity;
4546
import io.trino.sql.tree.ExplainType;
4647
import io.trino.testing.AbstractTestQueryFramework;
4748
import io.trino.testing.MaterializedRow;
@@ -1004,6 +1005,47 @@ public void testMaterializedViewWithNonDeterministicFunction()
10041005
assertUpdate("DROP TABLE " + sourceTableName);
10051006
}
10061007

1008+
@Test
1009+
public void testMaterializedViewWithSessionScopedExpressions()
1010+
{
1011+
String sourceTableName = "source_table_" + randomNameSuffix();
1012+
assertUpdate("CREATE TABLE " + sourceTableName + " (value INTEGER)");
1013+
assertUpdate("INSERT INTO " + sourceTableName + " VALUES 1", 1);
1014+
1015+
// Session-scoped expressions (current_user, current_catalog, current_schema, current_path)
1016+
// are constants for materialized views (fixed at creation time), so the MV should be FRESH after refresh
1017+
String mvName = "mv_session_scoped_" + randomNameSuffix();
1018+
assertUpdate("CREATE MATERIALIZED VIEW " + mvName + " AS SELECT *, current_user AS created_by FROM " + sourceTableName);
1019+
1020+
assertFreshness(mvName, "STALE");
1021+
assertUpdate("REFRESH MATERIALIZED VIEW " + mvName, 1);
1022+
assertFreshness(mvName, "FRESH");
1023+
assertQuery("SELECT created_by FROM " + mvName, "VALUES 'user'");
1024+
1025+
// A different user querying the MV still sees the original creator's name
1026+
// because the MV is FRESH and returns cached data
1027+
Session otherUserSession = Session.builder(getSession())
1028+
.setIdentity(Identity.ofUser("other_user"))
1029+
.build();
1030+
assertQuery(otherUserSession, "SELECT created_by FROM " + mvName, "VALUES 'user'");
1031+
1032+
assertUpdate("INSERT INTO " + sourceTableName + " VALUES 2", 1);
1033+
assertFreshness(mvName, "STALE");
1034+
// Stale MV still serves cached data from storage
1035+
assertQuery(otherUserSession, "SELECT created_by FROM " + mvName, "VALUES 'user'");
1036+
// Refresh by a different user picks up the new row
1037+
assertUpdate(otherUserSession, "REFRESH MATERIALIZED VIEW " + mvName, 1);
1038+
assertFreshness(mvName, "FRESH");
1039+
// TODO https://github.com/trinodb/trino/issues/28738 session-scoped expressions should resolve using
1040+
// the MV owner's identity during refresh (like the stale inline path does via analyzeView), but currently
1041+
// the refresh path resolves them from the refreshing user's session.
1042+
// When fixed, this should be: VALUES ('user'), ('user')
1043+
assertQuery("SELECT created_by FROM " + mvName, "VALUES ('user'), ('other_user')");
1044+
1045+
assertUpdate("DROP MATERIALIZED VIEW " + mvName);
1046+
assertUpdate("DROP TABLE " + sourceTableName);
1047+
}
1048+
10071049
@Test
10081050
public void testMaterializedViewWithNonDeterministicFunctionAndGracePeriod()
10091051
{

0 commit comments

Comments
 (0)