diff --git a/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts b/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts index c6e5911fbe..3891ad67b0 100644 --- a/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts +++ b/apps/desktop/src/lib/__tests__/sql/sqlStatementRanges.spec.ts @@ -71,6 +71,15 @@ BEGIN SELECT 1 + 2 INTO PRE_TRD_DATE FROM DUAL; END;`; +const gaussDbNestedProcedure = `CREATE OR REPLACE PROCEDURE public.dbx_issue_4318() +AS +BEGIN + BEGIN + NULL; + END; + NULL; +END;`; + const mysqlRoutineFixture = `CREATE PROCEDURE p() BEGIN SELECT 1; @@ -210,6 +219,10 @@ describe("splitSqlStatementRanges", () => { expect(rangeSqlTexts(splitSqlStatementRanges(oracleIssue2405PlSql, "oracle"))).toEqual([oracleIssue2405PlSql]); }); + it("keeps nested GaussDB procedure blocks together", () => { + expect(rangeSqlTexts(splitSqlStatementRanges(gaussDbNestedProcedure, "gaussdb"))).toEqual([gaussDbNestedProcedure]); + }); + it("keeps SAP HANA DO blocks together", () => { const ranges = splitSqlStatementRanges(sapHanaDoBlockFixture, "saphana"); @@ -720,6 +733,11 @@ WHERE request_json LIKE '%"paperFlag":null%';`; } }); + it("returns the full GaussDB procedure for cursors after a nested block", () => { + const outerNull = indexOf(gaussDbNestedProcedure, "NULL;", 2); + expect(statementRangeAtCursor(gaussDbNestedProcedure, outerNull, "gaussdb")?.sql.trim()).toBe(gaussDbNestedProcedure); + }); + it("returns the full SAP HANA DO block for cursors inside nested statements", () => { const range = statementRangeAtCursor(sapHanaDoBlockFixture, indexOf(sapHanaDoBlockFixture, "Result"), "saphana"); diff --git a/apps/desktop/src/lib/sql/sqlStatementRanges.ts b/apps/desktop/src/lib/sql/sqlStatementRanges.ts index 649274eaa1..0a95e9701f 100644 --- a/apps/desktop/src/lib/sql/sqlStatementRanges.ts +++ b/apps/desktop/src/lib/sql/sqlStatementRanges.ts @@ -1669,14 +1669,15 @@ function oraclePlSqlBlockIsComplete(sql: string): boolean { if (token.kind !== "word") continue; if (token.value === "DECLARE") { - stack.push("BLOCK"); + stack.push("DECLARATION"); continue; } if (token.value === "BEGIN") { if (tokens[index - 1]?.kind === "word" && tokens[index - 1]?.value === "TRANSACTION") continue; const previous = previousWordToken(tokens, index); if (previous === "END") continue; - if (stack[stack.length - 1] !== "BLOCK") stack.push("BLOCK"); + if (stack[stack.length - 1] === "DECLARATION") stack[stack.length - 1] = "BLOCK"; + else stack.push("BLOCK"); continue; } if (token.value === "IF") {