From b6049d80d07ee57aca5de4f20243c8204aa2f56e Mon Sep 17 00:00:00 2001 From: zipg Date: Thu, 1 Oct 2026 22:33:14 +0800 Subject: [PATCH] fix(iris): disable bracket identifier scanning in ranges --- .github/workflows/ci.yml | 2 ++ ...eryEditor.componentSplit.integration.spec.ts | 14 ++++++++++++++ .../__tests__/sql/sqlStatementRanges.spec.ts | 14 ++++++++++++++ apps/desktop/src/lib/sql/sqlStatementRanges.ts | 3 ++- docs/screenshots/issue-10706-after.jpg | Bin 0 -> 12848 bytes docs/screenshots/issue-10706-before.jpg | Bin 0 -> 13277 bytes 6 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 docs/screenshots/issue-10706-after.jpg create mode 100644 docs/screenshots/issue-10706-before.jpg diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 9815718c2b..b7ec6f3aac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -68,6 +68,8 @@ jobs: runs-on: ubuntu-24.04 env: NPM_CONFIG_LOGLEVEL: error + # Cold vue-tsc runs exceed 4 GiB; public Linux runners provide 16 GiB RAM. + NODE_OPTIONS: --max-old-space-size=8192 steps: - uses: actions/checkout@v7 diff --git a/apps/desktop/src/components/editor/__tests__/QueryEditor.componentSplit.integration.spec.ts b/apps/desktop/src/components/editor/__tests__/QueryEditor.componentSplit.integration.spec.ts index 0af33d9111..84974f9503 100644 --- a/apps/desktop/src/components/editor/__tests__/QueryEditor.componentSplit.integration.spec.ts +++ b/apps/desktop/src/components/editor/__tests__/QueryEditor.componentSplit.integration.spec.ts @@ -79,6 +79,20 @@ function keydown(target: HTMLElement, key: string) { } describe("QueryEditor component split integration", () => { + it("executes each IRIS query separately after the Contains operator", async () => { + const first = "select * from oec_order_adminstatus where STAT_Code [ '123'"; + const second = "select top 10 * from Ens_HOSDocument"; + const source = first + "\n\n" + second; + const { editor, view, onExecute } = await mountEditor({ modelValue: source, databaseType: "iris", dialect: "postgres" }); + view.dispatch({ selection: { anchor: source.indexOf(second) + 7 } }); + expect(editor.requestExecute({ bypassPicker: true })).toBe(true); + expect(onExecute.mock.lastCall?.[0].selectedSql).toBe(second); + + view.dispatch({ selection: { anchor: 7 } }); + expect(editor.requestExecute({ bypassPicker: true })).toBe(true); + expect(onExecute.mock.lastCall?.[0].selectedSql).toBe(first); + }); + it("preserves upstream structure-peek focus and insertion context across updates and unmount", async () => { const { view, props, unmount } = await mountEditor({ connectionId: "peek-a", database: "demo", schema: "public" }); expect(queryEditorInsertContext(view)).toEqual({ connectionId: "peek-a", database: "demo", schema: "public", databaseType: "mysql" }); diff --git a/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts b/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts index 37ddcf48f6..18092b7bdf 100644 --- a/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts +++ b/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts @@ -1684,6 +1684,20 @@ SET t.no = s.no`; }); describe("executableStatementRanges", () => { + it.each(["\n\n", ";\n", "; "])("keeps SELECT after an IRIS Contains operator separate with separator %j", (separator) => { + const first = "select * from oec_order_adminstatus where STAT_Code [ '123'"; + const second = "select top 10 * from Ens_HOSDocument"; + const sql = first + separator + second; + + expect(rangeSqlTexts(executableStatementRanges(sql, "iris"))).toEqual([first, second]); + expect(currentExecutableStatementRange(sql, sql.indexOf(second) + 7, "iris")?.sql).toBe(second); + }); + + it("keeps SQL Server bracket identifiers containing semicolons quoted", () => { + const sql = "SELECT [name;part] FROM [table;part]; SELECT 2;"; + expect(rangeSqlTexts(executableStatementRanges(sql, "sqlserver"))).toEqual(["SELECT [name;part] FROM [table;part]", "SELECT 2"]); + }); + it.each(["doris", "starrocks"] as const)("keeps %s half-open range partitions from swallowing the next statement", (databaseType) => { const first = `CREATE TABLE fixed_partitions_1 ( sale_date date NULL, diff --git a/apps/desktop/src/lib/sql/sqlStatementRanges.ts b/apps/desktop/src/lib/sql/sqlStatementRanges.ts index 6afe36f3fc..73d2b6a331 100644 --- a/apps/desktop/src/lib/sql/sqlStatementRanges.ts +++ b/apps/desktop/src/lib/sql/sqlStatementRanges.ts @@ -214,7 +214,8 @@ function splitElasticsearchRestRequestRanges(sql: string): RawStatement[] | unde type QuoteState = "none" | "single" | "double" | "backtick" | "bracket" | "dollar"; function usesBracketIdentifierQuotes(databaseType?: DatabaseType): boolean { - return databaseType !== "doris" && databaseType !== "starrocks"; + // IRIS uses `[` as its Contains operator, with no matching `]`. + return databaseType !== "doris" && databaseType !== "starrocks" && databaseType !== "iris"; } const COMMON_SOFT_STATEMENT_START_KEYWORDS = [ diff --git a/docs/screenshots/issue-10706-after.jpg b/docs/screenshots/issue-10706-after.jpg new file mode 100644 index 0000000000000000000000000000000000000000..19d24b5be6e1a765909ce4120d3f5ca88011c5d9 GIT binary patch literal 12848 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 Wi25%B{m01v^wR(DG4k2{{{I6ft}NOB literal 0 HcmV?d00001 diff --git a/docs/screenshots/issue-10706-before.jpg b/docs/screenshots/issue-10706-before.jpg new file mode 100644 index 0000000000000000000000000000000000000000..3ddacc5e943bdd5bb6169f9855e02de2638e60a3 GIT binary patch literal 13277 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 literal 0 HcmV?d00001