|
18 | 18 | import com.starrocks.catalog.MaterializedView; |
19 | 19 | import com.starrocks.common.util.RuntimeProfile; |
20 | 20 | import com.starrocks.common.util.UUIDUtil; |
| 21 | +import com.starrocks.plugin.AuditEvent; |
21 | 22 | import com.starrocks.qe.ConnectContext; |
22 | 23 | import com.starrocks.scheduler.mv.pct.MVPCTRefreshProcessor; |
23 | 24 | import com.starrocks.scheduler.persist.MVTaskRunExtraMessage; |
@@ -153,6 +154,55 @@ public void testPlanBuilderMessageTracing() throws Exception { |
153 | 154 | starRocksAssert.dropMaterializedView("test_mv_plan_builder"); |
154 | 155 | } |
155 | 156 |
|
| 157 | + /** |
| 158 | + * Regression test: async MV refresh runs the INSERT OVERWRITE through |
| 159 | + * StmtExecutor.handleDMLStmtWithProfile() directly and bypasses StmtExecutor.execute(), where |
| 160 | + * recordExecStatsIntoContext() is invoked. Before the fix the execution statistics were never |
| 161 | + * flushed into the audit event builder, so the audit log lost CpuCostNs/MemCostBytes/ScanRows |
| 162 | + * for every MV refresh (regression of #56257). This verifies they are recorded again. |
| 163 | + */ |
| 164 | + @Test |
| 165 | + public void testMVRefreshRecordsAuditStats() throws Exception { |
| 166 | + // Insert data so the refresh issues a real INSERT OVERWRITE that produces exec statistics. |
| 167 | + executeInsertSql(connectContext, "insert into test.tbl1 partition(p1) values('2022-01-02', 1, 10)"); |
| 168 | + |
| 169 | + starRocksAssert.useDatabase("test") |
| 170 | + .withMaterializedView("CREATE MATERIALIZED VIEW `test_mv_audit_stats` " + |
| 171 | + "REFRESH DEFERRED MANUAL\n" + |
| 172 | + "PROPERTIES (\n" + |
| 173 | + "\"replication_num\" = \"1\"" + |
| 174 | + ")\n" + |
| 175 | + "AS SELECT k1, k2, v1 FROM test.tbl1;"); |
| 176 | + |
| 177 | + Database testDb = GlobalStateMgr.getCurrentState().getLocalMetastore().getDb("test"); |
| 178 | + MaterializedView mv = ((MaterializedView) GlobalStateMgr.getCurrentState().getLocalMetastore() |
| 179 | + .getTable(testDb.getFullName(), "test_mv_audit_stats")); |
| 180 | + Assertions.assertNotNull(mv); |
| 181 | + |
| 182 | + Task task = TaskBuilder.buildMvTask(mv, testDb.getFullName()); |
| 183 | + task.getProperties().put(TaskRun.IS_TEST, "true"); |
| 184 | + |
| 185 | + TaskRun taskRun = TaskRunBuilder.newBuilder(task).build(); |
| 186 | + taskRun.initStatus(UUIDUtil.genUUID().toString(), System.currentTimeMillis()); |
| 187 | + taskRun.executeTaskRun(); |
| 188 | + |
| 189 | + // The refresh uses its own ConnectContext; read the audit event built on that context. |
| 190 | + ConnectContext runCtx = taskRun.getRunCtx(); |
| 191 | + Assertions.assertNotNull(runCtx, "MV refresh ConnectContext should be available"); |
| 192 | + AuditEvent auditEvent = runCtx.getAuditEventBuilder().build(); |
| 193 | + |
| 194 | + // Default value is -1 (dropped from the audit line by AuditLogBuilder). A non-default value |
| 195 | + // proves the stats were flushed into the builder on the MV refresh path. |
| 196 | + Assertions.assertNotEquals(-1L, auditEvent.cpuCostNs, |
| 197 | + "MV refresh audit log should record CpuCostNs"); |
| 198 | + Assertions.assertNotEquals(-1L, auditEvent.memCostBytes, |
| 199 | + "MV refresh audit log should record MemCostBytes"); |
| 200 | + Assertions.assertNotEquals(-1L, auditEvent.scanRows, |
| 201 | + "MV refresh audit log should record ScanRows"); |
| 202 | + |
| 203 | + starRocksAssert.dropMaterializedView("test_mv_audit_stats"); |
| 204 | + } |
| 205 | + |
156 | 206 | /** |
157 | 207 | * Test that MVPCTBasedRefreshProcessor correctly updates task run status definition. |
158 | 208 | */ |
|
0 commit comments