Skip to content

Commit 644ae60

Browse files
Youngwbclaude
andcommitted
[Enhancement] Introduce SCHEDULE keyword as ASYNC synonym for MV refresh (#72329)
Signed-off-by: Youngwb <yangwenbo_mailbox@163.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> (cherry picked from commit 112df75)
1 parent e873c66 commit 644ae60

11 files changed

Lines changed: 65 additions & 18 deletions

File tree

docs/en/sql-reference/sql-statements/materialized_view/ALTER_MATERIALIZED_VIEW.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ ALTER MATERIALIZED VIEW lo_mv1 RENAME lo_mv1_new_name;
7070
Example 2: Alter the refresh interval of the materialized view.
7171

7272
```SQL
73-
ALTER MATERIALIZED VIEW lo_mv2 REFRESH ASYNC EVERY(INTERVAL 1 DAY);
73+
ALTER MATERIALIZED VIEW lo_mv2 REFRESH SCHEDULE EVERY(INTERVAL 1 DAY);
7474
```
7575

7676
Example 3: Alter the timeout duration for the materialized view refresh tasks to 1 hour (default).

docs/en/sql-reference/sql-statements/materialized_view/CREATE_MATERIALIZED_VIEW.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ CREATE MATERIALIZED VIEW [IF NOT EXISTS] [database.]<mv_name>
164164
-- refresh_moment
165165
[IMMEDIATE | DEFERRED]
166166
-- refresh_scheme
167-
[ASYNC | ASYNC [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
167+
[ASYNC | SCHEDULE [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
168168
]
169169
-- partition_expression
170170
[PARTITION BY
@@ -250,7 +250,7 @@ The refresh moment of the materialized view. Default value: `IMMEDIATE`. Valid v
250250
The refresh strategy of the asynchronous materialized view. Valid values:
251251

252252
- `ASYNC`: Automatic refresh mode. Each time the base table data changes, the materialized view is automatically refreshed.
253-
- `ASYNC [START (<start_time>)] EVERY(INTERVAL <interval>)`: Regular refresh mode. The materialized view is refreshed regularly at the interval defined. You can specify the interval as `EVERY (interval n day/hour/minute/second)` using the following units: `DAY`, `HOUR`, `MINUTE`, and `SECOND`. The default value is `10 MINUTE`. You can further specify the refresh start time as `START('yyyy-MM-dd hh:mm:ss')`. If the start time is not specified, the current time is used. Example: `ASYNC START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`.
253+
- `SCHEDULE [START (<start_time>)] EVERY(INTERVAL <interval>)`: Regular refresh mode. The materialized view is refreshed regularly at the interval defined. You can specify the interval as `EVERY (interval n day/hour/minute/second)` using the following units: `DAY`, `HOUR`, `MINUTE`, and `SECOND`. The default value is `10 MINUTE`. You can further specify the refresh start time as `START('yyyy-MM-dd hh:mm:ss')`. If the start time is not specified, the current time is used. Example: `SCHEDULE START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`. The legacy form `ASYNC [START (...)] EVERY (...)` is still accepted for backward compatibility but `SHOW CREATE MATERIALIZED VIEW` always renders the scheduled form with `SCHEDULE`.
254254
- `MANUAL`: Manual refresh mode. The materialized view will not be refreshed unless you trigger a refresh task manually.
255255

256256
If this parameter is not specified, the default value `MANUAL` is used.

docs/ja/sql-reference/sql-statements/materialized_view/ALTER_MATERIALIZED_VIEW.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ ALTER MATERIALIZED VIEW lo_mv1 RENAME lo_mv1_new_name;
7272
例2: マテリアライズドビューのリフレッシュ間隔を変更します。
7373

7474
```SQL
75-
ALTER MATERIALIZED VIEW lo_mv2 REFRESH ASYNC EVERY(INTERVAL 1 DAY);
75+
ALTER MATERIALIZED VIEW lo_mv2 REFRESH SCHEDULE EVERY(INTERVAL 1 DAY);
7676
```
7777

7878
例3: マテリアライズドビューのリフレッシュタスクのタイムアウト期間を1時間(デフォルト)に変更します。

docs/ja/sql-reference/sql-statements/materialized_view/CREATE_MATERIALIZED_VIEW.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ CREATE MATERIALIZED VIEW [IF NOT EXISTS] [database.]<mv_name>
166166
-- refresh_moment
167167
[IMMEDIATE | DEFERRED]
168168
-- refresh_scheme
169-
[ASYNC | ASYNC [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
169+
[ASYNC | SCHEDULE [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
170170
]
171171
-- partition_expression
172172
[PARTITION BY
@@ -252,7 +252,7 @@ AS
252252
非同期マテリアライズドビューのリフレッシュ戦略。有効な値:
253253

254254
- `ASYNC`: 自動リフレッシュモード。ベーステーブルデータが変更されるたびに、マテリアライズドビューが自動的にリフレッシュされます。
255-
- `ASYNC [START (<start_time>)] EVERY(INTERVAL <interval>)`: 定期リフレッシュモード。定義された間隔でマテリアライズドビューが定期的にリフレッシュされます。間隔は`EVERY (interval n day/hour/minute/second)`として指定できます。使用可能な単位は`DAY``HOUR``MINUTE``SECOND`です。デフォルト値は`10 MINUTE`です。リフレッシュ開始時間を`START('yyyy-MM-dd hh:mm:ss')`としてさらに指定できます。開始時間が指定されていない場合、現在の時間が使用されます。例: `ASYNC START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`
255+
- `SCHEDULE [START (<start_time>)] EVERY(INTERVAL <interval>)`: 定期リフレッシュモード。定義された間隔でマテリアライズドビューが定期的にリフレッシュされます。間隔は`EVERY (interval n day/hour/minute/second)`として指定できます。使用可能な単位は`DAY``HOUR``MINUTE``SECOND`です。デフォルト値は`10 MINUTE`です。リフレッシュ開始時間を`START('yyyy-MM-dd hh:mm:ss')`としてさらに指定できます。開始時間が指定されていない場合、現在の時間が使用されます。例: `SCHEDULE START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`。互換性のため `ASYNC [START (...)] EVERY (...)` も引き続き受け付けますが、`SHOW CREATE MATERIALIZED VIEW` の出力は常に `SCHEDULE` で表示されます
256256
- `MANUAL`: 手動リフレッシュモード。リフレッシュタスクを手動でトリガーしない限り、マテリアライズドビューはリフレッシュされません。
257257

258258
このパラメータが指定されていない場合、デフォルト値`MANUAL`が使用されます。

docs/zh/sql-reference/sql-statements/materialized_view/ALTER_MATERIALIZED_VIEW.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ ALTER MATERIALIZED VIEW lo_mv1 RENAME lo_mv1_new_name;
7171
示例二:修改物化视图刷新间隔
7272

7373
```SQL
74-
ALTER MATERIALIZED VIEW lo_mv2 REFRESH ASYNC EVERY(INTERVAL 1 DAY);
74+
ALTER MATERIALIZED VIEW lo_mv2 REFRESH SCHEDULE EVERY(INTERVAL 1 DAY);
7575
```
7676

7777
示例三:修改物化视图属性,调整物化视图刷新 Timeout 为一小时(默认)。

docs/zh/sql-reference/sql-statements/materialized_view/CREATE_MATERIALIZED_VIEW.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ CREATE MATERIALIZED VIEW [IF NOT EXISTS] [database.]<mv_name>
164164
-- refresh_moment
165165
[IMMEDIATE | DEFERRED]
166166
-- refresh_scheme
167-
[ASYNC | ASYNC [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
167+
[ASYNC | SCHEDULE [START (<start_time>)] EVERY (INTERVAL <refresh_interval>) | MANUAL]
168168
]
169169
-- partition_expression
170170
[PARTITION BY
@@ -248,7 +248,7 @@ AS
248248
物化视图的刷新方式。该参数支持如下值:
249249

250250
- `ASYNC`: 自动刷新模式。每当基表数据发生变化时,物化视图会自动刷新。
251-
- `ASYNC [START (<start_time>)] EVERY(INTERVAL <interval>)`: 定时刷新模式。物化视图将按照定义的间隔定时刷新。您可以使用 `DAY`(天)、`HOUR`(小时)、`MINUTE`(分钟)和 `SECOND`(秒)作为单位指定间隔,格式为 `EVERY (interval n day/hour/minute/second)`。默认值为 `10 MINUTE`(10 分钟)。您还可以进一步指定刷新起始时间,格式为 `START('yyyy-MM-dd hh:mm:ss')`。如未指定起始时间,默认使用当前时间。示例:`ASYNC START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`
251+
- `SCHEDULE [START (<start_time>)] EVERY(INTERVAL <interval>)`: 定时刷新模式。物化视图将按照定义的间隔定时刷新。您可以使用 `DAY`(天)、`HOUR`(小时)、`MINUTE`(分钟)和 `SECOND`(秒)作为单位指定间隔,格式为 `EVERY (interval n day/hour/minute/second)`。默认值为 `10 MINUTE`(10 分钟)。您还可以进一步指定刷新起始时间,格式为 `START('yyyy-MM-dd hh:mm:ss')`。如未指定起始时间,默认使用当前时间。示例:`SCHEDULE START ('2023-09-12 16:30:25') EVERY (INTERVAL 5 MINUTE)`。为兼容旧版本,`ASYNC [START (...)] EVERY (...)` 仍然被接受,但 `SHOW CREATE MATERIALIZED VIEW` 输出的定时刷新部分始终使用 `SCHEDULE`
252252
- `MANUAL`: 手动刷新模式。除非手动触发刷新任务,否则物化视图不会刷新。
253253

254254
如果不指定该参数,则默认使用 MANUAL 方式。

fe/fe-core/src/main/java/com/starrocks/catalog/MaterializedView.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1906,10 +1906,18 @@ public String getMaterializedViewDdlStmt(boolean simple, boolean isReplay) {
19061906
if (refreshScheme == null) {
19071907
sb.append("\nREFRESH ").append("UNKNOWN");
19081908
} else {
1909+
// Prefer the SCHEDULE keyword for scheduled refresh (ASYNC + EVERY). ASYNC is kept
1910+
// as the legacy synonym in the parser; for bare ASYNC (no EVERY) we still emit
1911+
// ASYNC because bare SCHEDULE is not a valid form.
1912+
String typeName = refreshScheme.getType().name();
1913+
if (refreshScheme.getType() == MaterializedViewRefreshType.ASYNC
1914+
&& refreshScheme.getAsyncRefreshContext().getTimeUnit() != null) {
1915+
typeName = "SCHEDULE";
1916+
}
19091917
if (refreshScheme.getMoment().equals(RefreshMoment.DEFERRED)) {
1910-
sb.append(String.format("\nREFRESH %s %s", refreshScheme.getMoment(), refreshScheme.getType()));
1918+
sb.append(String.format("\nREFRESH %s %s", refreshScheme.getMoment(), typeName));
19111919
} else {
1912-
sb.append("\nREFRESH ").append(refreshScheme.getType());
1920+
sb.append("\nREFRESH ").append(typeName);
19131921
}
19141922
}
19151923
if (refreshScheme != null && refreshScheme.getType() == MaterializedViewRefreshType.ASYNC) {

fe/fe-core/src/main/java/com/starrocks/sql/parser/AstBuilder.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9155,7 +9155,8 @@ public ParseNode visitRefreshSchemeDesc(com.starrocks.sql.parser.StarRocksParser
91559155
} else if (context.IMMEDIATE() != null) {
91569156
refreshMoment = RefreshSchemeClause.RefreshMoment.IMMEDIATE;
91579157
}
9158-
if (context.ASYNC() != null) {
9158+
// SCHEDULE is the preferred keyword; ASYNC is kept as a synonym for compatibility.
9159+
if (context.ASYNC() != null || context.SCHEDULE() != null) {
91599160
boolean defineStartTime = false;
91609161
if (context.START() != null) {
91619162
NodePosition timePos = createPos(context.string());

fe/fe-core/src/test/java/com/starrocks/analysis/AlterMaterializedViewTest.java

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,14 +140,19 @@ public void testAlterRefreshScheme() throws Exception {
140140
MaterializedView mv = starRocksAssert.getMv("test", mvName);
141141
String taskDefinition = mv.getTaskDefinition();
142142
for (String refresh : refreshSchemes) {
143-
// alter
143+
// alter — ASYNC is kept as a legacy synonym; SCHEDULE is the preferred keyword
144+
// for the EVERY form and is what SHOW CREATE displays.
144145
String sql = String.format("alter materialized view %s refresh %s", mvName, refresh);
145146
starRocksAssert.ddl(sql);
146147

147-
// verify
148148
mv = starRocksAssert.getMv("test", mvName);
149149
String showCreateStmt = mv.getMaterializedViewDdlStmt(false);
150-
Assertions.assertTrue(showCreateStmt.contains(refresh),
150+
// SHOW CREATE rewrites "ASYNC ... EVERY ..." to "SCHEDULE ... EVERY ..." but leaves
151+
// bare ASYNC (no EVERY) unchanged.
152+
String expected = refresh.contains("EVERY")
153+
? refresh.replaceFirst("^ASYNC", "SCHEDULE")
154+
: refresh;
155+
Assertions.assertTrue(showCreateStmt.contains(expected),
151156
String.format("alter to %s \nbut got \n%s", refresh, showCreateStmt));
152157
Assertions.assertEquals(taskDefinition, mv.getTaskDefinition());
153158
}

fe/fe-core/src/test/java/com/starrocks/analysis/ShowCreateMaterializedViewStmtTest.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,13 +237,46 @@ public void testMvUniqueConstraintsTableNotExist() throws Exception {
237237
Assertions.assertThrows(SemanticException.class, () -> table.getUniqueConstraints().get(0).getUniqueColumnNames(table));
238238
}
239239

240+
@Test
241+
public void testAsyncIsSynonymForScheduleAndShowCreatePrefersSchedule() throws Exception {
242+
final String mvName = "test_mv_async_synonym";
243+
starRocksAssert.ddl("drop materialized view if exists " + mvName);
244+
// ASYNC must remain accepted as a synonym.
245+
starRocksAssert.withMaterializedView("CREATE MATERIALIZED VIEW " + mvName +
246+
" DISTRIBUTED BY HASH(`k1`) BUCKETS 3" +
247+
" REFRESH ASYNC EVERY(INTERVAL 1 HOUR)" +
248+
" AS SELECT k1, k2 FROM test.tbl1");
249+
MaterializedView mv = starRocksAssert.getMv(starRocksAssert.getCtx().getDatabase(), mvName);
250+
List<String> ddl = Lists.newArrayList();
251+
AstToStringBuilder.getDdlStmt(mv, ddl, null, null, false, true);
252+
Assertions.assertTrue(ddl.get(0).contains("REFRESH SCHEDULE EVERY(INTERVAL 1 HOUR)"),
253+
"SHOW CREATE should display SCHEDULE, got: " + ddl.get(0));
254+
Assertions.assertFalse(ddl.get(0).contains("REFRESH ASYNC"),
255+
"SHOW CREATE should not display ASYNC, got: " + ddl.get(0));
256+
starRocksAssert.dropMaterializedView(mvName);
257+
258+
// SCHEDULE should also parse and produce the same display.
259+
starRocksAssert.withMaterializedView("CREATE MATERIALIZED VIEW " + mvName +
260+
" DISTRIBUTED BY HASH(`k1`) BUCKETS 3" +
261+
" REFRESH SCHEDULE EVERY(INTERVAL 1 HOUR)" +
262+
" AS SELECT k1, k2 FROM test.tbl1");
263+
mv = starRocksAssert.getMv(starRocksAssert.getCtx().getDatabase(), mvName);
264+
ddl.clear();
265+
AstToStringBuilder.getDdlStmt(mv, ddl, null, null, false, true);
266+
Assertions.assertTrue(ddl.get(0).contains("REFRESH SCHEDULE EVERY(INTERVAL 1 HOUR)"),
267+
"SHOW CREATE should display SCHEDULE, got: " + ddl.get(0));
268+
starRocksAssert.dropMaterializedView(mvName);
269+
}
270+
240271
public static Stream<Arguments> genTestArguments() {
272+
// Bare ASYNC (without EVERY) is the legacy form retained for backward compatibility;
273+
// SCHEDULE is the preferred keyword for scheduled refresh and requires EVERY.
241274
List<String> refreshArgumentsList = Lists.newArrayList(
242275
"REFRESH MANUAL",
243276
"REFRESH DEFERRED MANUAL",
244277
"REFRESH ASYNC",
245-
"REFRESH ASYNC EVERY(INTERVAL 1 HOUR)",
246-
"REFRESH ASYNC START(\"1998-01-01 00:00:00\") EVERY(INTERVAL 1 HOUR)"
278+
"REFRESH SCHEDULE EVERY(INTERVAL 1 HOUR)",
279+
"REFRESH SCHEDULE START(\"1998-01-01 00:00:00\") EVERY(INTERVAL 1 HOUR)"
247280
);
248281
List<String> orderByList = Lists.newArrayList("", "ORDER BY (k3)");
249282
List<String> propertiesList = Lists.newArrayList(

0 commit comments

Comments
 (0)