fix(sql): preserve StarRocks materialized view statements

This commit is contained in:
Guoyu Su
2026-09-03 01:45:20 +08:00
committed by GitHub
parent d38be39e03
commit 1ed4b42955
2 changed files with 74 additions and 0 deletions
@@ -844,6 +844,67 @@ GET /_cat/indices`;
expect(range?.sql.trim()).toBe("UPDATE users\nSET name = 'a'\nWHERE id = 1");
});
it("keeps StarRocks asynchronous materialized-view clauses in the CREATE statement", () => {
const createSql = `CREATE MATERIALIZED VIEW mv_monthly_events
PARTITION BY date_trunc('month', event_time)
DISTRIBUTED BY RANDOM BUCKETS 1
REFRESH ASYNC
AS
SELECT
id,
event_time,
amount
FROM base_events`;
const sql = `${createSql}\nREFRESH MATERIALIZED VIEW mv_monthly_events;`;
for (const marker of ["CREATE", "PARTITION", "DISTRIBUTED", "REFRESH ASYNC", "SELECT", "base_events"]) {
expect(statementRangeAtCursor(sql, indexOf(sql, marker), "starrocks")?.sql.trim()).toBe(createSql);
}
expect(statementRangeAtCursor(sql, indexOf(sql, "REFRESH MATERIALIZED"), "starrocks")?.sql.trim()).toBe("REFRESH MATERIALIZED VIEW mv_monthly_events");
expect(rangeSqlTexts(executableStatementRanges(sql, "starrocks"))).toEqual([createSql, "REFRESH MATERIALIZED VIEW mv_monthly_events"]);
});
it("keeps StarRocks scheduled materialized-view clauses in the CREATE statement", () => {
const sql = `CREATE MATERIALIZED VIEW mv_daily_events
REFRESH SCHEDULE EVERY (INTERVAL 1 DAY)
AS
SELECT id FROM base_events`;
expect(statementRangeAtCursor(sql, indexOf(sql, "REFRESH"), "starrocks")?.sql.trim()).toBe(sql);
expect(statementRangeAtCursor(sql, indexOf(sql, "SELECT"), "starrocks")?.sql.trim()).toBe(sql);
expect(rangeSqlTexts(executableStatementRanges(sql, "starrocks"))).toEqual([sql]);
});
it("keeps StarRocks manual materialized-view refresh in the CREATE statement", () => {
const sql = `CREATE MATERIALIZED VIEW mv_manual_events
REFRESH MANUAL
AS
SELECT id FROM base_events`;
expect(statementRangeAtCursor(sql, indexOf(sql, "REFRESH"), "starrocks")?.sql.trim()).toBe(sql);
expect(statementRangeAtCursor(sql, indexOf(sql, "SELECT"), "starrocks")?.sql.trim()).toBe(sql);
expect(rangeSqlTexts(executableStatementRanges(sql, "starrocks"))).toEqual([sql]);
});
it("keeps StarRocks deferred and immediate refresh modifiers with async on the next line", () => {
const deferredSql = `CREATE MATERIALIZED VIEW mv_deferred_events
REFRESH DEFERRED ASYNC
AS
SELECT id FROM base_events`;
const immediateSql = `CREATE MATERIALIZED VIEW mv_immediate_events
REFRESH IMMEDIATE
ASYNC
AS
SELECT id FROM base_events`;
expect(statementRangeAtCursor(deferredSql, indexOf(deferredSql, "REFRESH"), "starrocks")?.sql.trim()).toBe(deferredSql);
expect(statementRangeAtCursor(deferredSql, indexOf(deferredSql, "SELECT"), "starrocks")?.sql.trim()).toBe(deferredSql);
expect(statementRangeAtCursor(immediateSql, indexOf(immediateSql, "REFRESH"), "starrocks")?.sql.trim()).toBe(immediateSql);
expect(statementRangeAtCursor(immediateSql, indexOf(immediateSql, "ASYNC"), "starrocks")?.sql.trim()).toBe(immediateSql);
expect(rangeSqlTexts(executableStatementRanges(deferredSql, "starrocks"))).toEqual([deferredSql]);
expect(rangeSqlTexts(executableStatementRanges(immediateSql, "starrocks"))).toEqual([immediateSql]);
});
it("keeps MySQL ALTER TABLE column comments with the column definition", () => {
const sql =
"ALTER TABLE `yb_course_order`\n ADD COLUMN `audit_status` tinyint(4) DEFAULT NULL\n COMMENT '审核状态:0-待审核,1-已通过,2-已拒绝',\n ADD COLUMN `close_reason` varchar(30) DEFAULT NULL\n COMMENT '关闭原因:timeout-超时关闭,cancel-取消关闭,refund-退款关闭',\n ADD COLUMN `paid_completion_time` datetime DEFAULT NULL\n COMMENT '订单完成支付(付清)时间 首次全额支付完成时记录,全部退款后不重置';";
@@ -261,6 +261,7 @@ const DATABASE_SOFT_STATEMENT_KEYWORDS: Partial<Record<DatabaseType, readonly st
const WITH_MAIN_STATEMENT_KEYWORDS = new Set(["SELECT", "INSERT", "UPDATE", "DELETE", "MERGE"]);
const EXPLAIN_STATEMENT_KEYWORDS = new Set(["SELECT", "WITH", "INSERT", "UPDATE", "DELETE", "MERGE", "CREATE", "ALTER", "DROP"]);
const CREATE_BODY_KEYWORDS = new Set(["SELECT", "WITH", "BEGIN", "DECLARE"]);
const STARROCKS_CREATE_MATERIALIZED_VIEW_REFRESH_MODIFIERS = new Set(["ASYNC", "MANUAL", "SCHEDULE", "DEFERRED", "IMMEDIATE"]);
const INSERT_BODY_KEYWORDS = new Set(["SELECT", "WITH"]);
const ALTER_BODY_KEYWORDS = new Set(["ADD", "ALTER", "COMMENT", "DROP", "MODIFY", "RENAME", "SET"]);
const CLICKHOUSE_ALTER_TABLE_HEADER = /^ALTER\s+TABLE\s+(?:(?:[A-Za-z_][\w$]*|`(?:``|[^`])+`|"(?:""|[^"])+")\s*\.\s*)?(?:[A-Za-z_][\w$]*|`(?:``|[^`])+`|"(?:""|[^"])+")(?:\s+ON\s+CLUSTER\s+(?:[A-Za-z_][\w$]*|`(?:``|[^`])+`|"(?:""|[^"])+"|'(?:''|[^'])+'))?\s*$/i;
@@ -762,6 +763,10 @@ function splitStatementRangeAtSoftStarts(sql: string, statement: RawStatement, d
continue;
}
if (currentBodyKeyword === "CREATE" && isStarRocksCreateMaterializedViewRefreshContinuation(sql, statement.from, lineStart.from, lineStart.keyword, databaseType, parameterOptions)) {
continue;
}
if (currentBodyKeyword === "CREATE" && isMysqlCreateTableOptionContinuation(sql, statement.from, lineStart.from, lineStart.keyword, databaseType)) {
continue;
}
@@ -1023,6 +1028,14 @@ function isMysqlCreateTableOptionContinuation(sql: string, statementFrom: number
return next === "=" || next === "'" || next === '"';
}
function isStarRocksCreateMaterializedViewRefreshContinuation(sql: string, statementFrom: number, lineStartFrom: number, keyword: string, databaseType?: DatabaseType, parameterOptions?: SqlParameterOptions): boolean {
if (databaseType !== "starrocks" || keyword !== "REFRESH") return false;
if (!startsWithSqlWords(sql, statementFrom, ["CREATE", "MATERIALIZED", "VIEW"], databaseType, parameterOptions)) return false;
const modifier = nextSqlWord(sql, lineStartFrom + keyword.length, databaseType, parameterOptions);
return modifier !== null && STARROCKS_CREATE_MATERIALIZED_VIEW_REFRESH_MODIFIERS.has(modifier);
}
function isClickHouseAlterTableUpdateContinuation(sql: string, statementFrom: number, lineStartFrom: number, keyword: string, databaseType?: DatabaseType): boolean {
if (databaseType !== "clickhouse" || keyword !== "UPDATE") return false;
return CLICKHOUSE_ALTER_TABLE_HEADER.test(sql.slice(statementFrom, lineStartFrom));