diff --git a/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts b/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts index 9acd7a894f..5328c75f88 100644 --- a/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts +++ b/apps/desktop/src/composables/__tests__/useSqlExecution.spec.ts @@ -670,6 +670,69 @@ SELECT @value AS Message;`; expect(executeCurrentSql).toHaveBeenCalledWith(sql, {}); }); + it.each([ + { + label: "JDBC MySQL", + config: { + ...connection("jdbc"), + driver_label: "MySQL JDBC", + connection_string: "jdbc:mysql://127.0.0.1:3306/app", + }, + }, + { + label: "GBase MySQL compatibility", + config: { + ...connection("gbase"), + driver_profile: "gbase", + driver_label: "GBase 8a", + }, + }, + ])("executes $label cursor procedures from the gutter without opening the parameter dialog", async ({ config }) => { + const sql = `CREATE PROCEDURE process_orders() + BEGIN + DECLARE done INT DEFAULT FALSE; + DECLARE order_id INT; + DECLARE cur_orders CURSOR FOR SELECT id FROM orders; + DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE; + OPEN cur_orders; + read_loop:LOOP + FETCH cur_orders INTO order_id; + IF done THEN LEAVE read_loop; END IF; + END LOOP read_loop; + CLOSE cur_orders; + END`; + const activeTab = ref({ ...queryTab("app"), sql }); + const activeConnection = ref(config); + const activeOutputView = ref<"result" | "summary" | "explain" | "chart">("result"); + const queryStore = useQueryStore(); + const executeCurrentSql = vi.spyOn(queryStore, "executeCurrentSql").mockImplementation(async () => { + if (activeTab.value) activeTab.value.result = { columns: [], rows: [], affected_rows: 0, execution_time_ms: 1 }; + }); + vi.spyOn(useHistoryStore(), "add").mockResolvedValue(undefined); + vi.spyOn(useConnectionStore(), "refreshObjectListTreeNode").mockResolvedValue(undefined); + + const execution = useSqlExecution({ + activeTab: computed(() => activeTab.value), + activeConnection: computed(() => activeConnection.value), + executableSql: computed(() => sql), + resolveExecutableSql: async () => sql, + activeOutputView, + }); + + await execution.tryExecute({ + fullSql: sql, + selectedSql: sql, + cursorPos: 0, + selectionFrom: 0, + selectionTo: sql.length, + editorViewportRequestId: 1, + }); + + expect(execution.showSqlParameterDialog.value).toBe(false); + expect(execution.sqlParameterNames.value).toEqual([]); + expect(executeCurrentSql).toHaveBeenCalledWith(sql, { sourceOffset: 0, onExecutionStarted: expect.any(Function) }); + }); + it("sends Doris STRUCT DDL unchanged without opening the parameter dialog", async () => { const sql = ` create table \`events\` ( diff --git a/apps/desktop/src/composables/useSqlExecution.ts b/apps/desktop/src/composables/useSqlExecution.ts index 08f11e9393..422e7d0860 100644 --- a/apps/desktop/src/composables/useSqlExecution.ts +++ b/apps/desktop/src/composables/useSqlExecution.ts @@ -235,7 +235,8 @@ export function useSqlExecution(deps: { } function prepareSqlParameterDialog(sql: string, sourceOffset?: number, options: SqlExecutionOptions = {}, continuation?: (sql: string, sourceOffset?: number) => Promise | void): boolean { - const databaseType = deps.activeConnection.value?.db_type; + const connection = deps.activeConnection.value; + const databaseType = effectiveDatabaseTypeForConnection(connection) ?? connection?.db_type; const toggles = resolveSqlVariableSyntaxToggles(settingsStore.editorSettings.sqlVariableSyntaxOverrides, databaseType, settingsStore.editorSettings.sqlVariableSubstitutionEnabled); const enabledSyntaxes = enabledSqlParameterSyntaxes(toggles); const parameters = extractSqlParameterDescriptors(sql, { databaseType, enabledSyntaxes });