From 00ca58fcdac75adc6697bbec47e697085a17e9db Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Tue, 20 Jan 2026 18:00:39 -0800 Subject: [PATCH 1/2] fix: support mysql-compatible databases that only support constant values in set statements --- .../atuin-desktop-runtime/src/blocks/mysql.rs | 18 ++++++++- .../runbooks/editor/blocks/MySQL/MySQL.tsx | 34 ++++++++++++++++ src/lib/blocks/common/SQL.tsx | 40 +++++++++++++++++++ src/lib/workflow/blocks/mysql.ts | 7 +++- 4 files changed, 96 insertions(+), 3 deletions(-) diff --git a/crates/atuin-desktop-runtime/src/blocks/mysql.rs b/crates/atuin-desktop-runtime/src/blocks/mysql.rs index 63909c2f..092000d3 100644 --- a/crates/atuin-desktop-runtime/src/blocks/mysql.rs +++ b/crates/atuin-desktop-runtime/src/blocks/mysql.rs @@ -33,6 +33,9 @@ pub struct Mysql { #[builder(default = 0)] pub auto_refresh: u32, + + #[builder(default = false)] + pub skip_sql_mode_init: bool, } impl FromDocument for Mysql { @@ -78,6 +81,12 @@ impl FromDocument for Mysql { .and_then(|v| v.as_u64()) .unwrap_or(0) as u32, ) + .skip_sql_mode_init( + props + .get("skipSqlModeInit") + .and_then(|v| v.as_bool()) + .unwrap_or(false), + ) .build(); Ok(mysql) @@ -170,7 +179,14 @@ impl SqlBlockBehavior for Mysql { } async fn create_pool(&self, uri: String) -> Result { - let opts = MySqlConnectOptions::from_str(&uri)?; + let mut opts = MySqlConnectOptions::from_str(&uri)?; + + // Skip sql_mode initialization for databases that don't support dynamic SET statements + // (e.g., StarRocks, Apache Doris) + if self.skip_sql_mode_init { + opts = opts.pipes_as_concat(false).no_engine_substitution(false); + } + Ok(MySqlPool::connect_with(opts).await?) } diff --git a/src/components/runbooks/editor/blocks/MySQL/MySQL.tsx b/src/components/runbooks/editor/blocks/MySQL/MySQL.tsx index cff95a3e..99587db4 100644 --- a/src/components/runbooks/editor/blocks/MySQL/MySQL.tsx +++ b/src/components/runbooks/editor/blocks/MySQL/MySQL.tsx @@ -1,4 +1,5 @@ import { DatabaseIcon } from "lucide-react"; +import { Switch } from "@heroui/react"; // @ts-ignore import { createReactBlockSpec } from "@blocknote/react"; @@ -25,6 +26,7 @@ interface SQLProps { setAutoRefresh: (autoRefresh: number) => void; setName: (name: string) => void; setDependency: (dependency: DependencySpec) => void; + setSkipSqlModeInit: (skip: boolean) => void; onCodeMirrorFocus?: () => void; } @@ -38,8 +40,28 @@ const MySQL = ({ collapseQuery, setCollapseQuery, setDependency, + setSkipSqlModeInit, onCodeMirrorFocus, }: SQLProps) => { + const settingsContent = ( +
+
+ + Skip SQL mode initialization + + + Enable for MySQL-compatible databases like StarRocks or Doris + +
+ +
+ ); + return ( ); }; @@ -72,6 +96,7 @@ export default createReactBlockSpec( uri: { default: "" }, autoRefresh: { default: 0 }, dependency: { default: "{}" }, + skipSqlModeInit: { default: false }, }, content: "none", }, @@ -133,6 +158,13 @@ export default createReactBlockSpec( }); }; + const setSkipSqlModeInit = (skip: boolean) => { + editor.updateBlock(block, { + // @ts-ignore + props: { ...block.props, skipSqlModeInit: skip }, + }); + }; + let dependency = DependencySpec.deserialize(block.props.dependency); let mysql = new MySqlBlock( block.id, @@ -141,6 +173,7 @@ export default createReactBlockSpec( block.props.query, block.props.uri, block.props.autoRefresh, + block.props.skipSqlModeInit, ); return ( @@ -154,6 +187,7 @@ export default createReactBlockSpec( collapseQuery={collapseQuery} setCollapseQuery={setCollapseQuery} setDependency={setDependency} + setSkipSqlModeInit={setSkipSqlModeInit} onCodeMirrorFocus={handleCodeMirrorFocus} /> ); diff --git a/src/lib/blocks/common/SQL.tsx b/src/lib/blocks/common/SQL.tsx index 519d6a06..81963113 100644 --- a/src/lib/blocks/common/SQL.tsx +++ b/src/lib/blocks/common/SQL.tsx @@ -12,6 +12,10 @@ import { ButtonGroup, Tooltip, DropdownSection, + Modal, + ModalContent, + ModalHeader, + ModalBody, } from "@heroui/react"; import { ArrowDownToLineIcon, @@ -24,6 +28,7 @@ import { RefreshCwIcon, Maximize2, Minimize2, + SettingsIcon, } from "lucide-react"; import CodeMirror, { Extension } from "@uiw/react-codemirror"; import { langs } from "@uiw/codemirror-extensions-langs"; @@ -77,6 +82,10 @@ interface SQLProps { setName: (name: string) => void; setDependency: (dependency: DependencySpec) => void; onCodeMirrorFocus?: () => void; + + // Optional settings content - if provided, shows settings icon + modal + settingsContent?: React.ReactNode; + settingsTitle?: string; } const autoRefreshChoices = [ @@ -111,12 +120,15 @@ const SQL = ({ sqlType, extensions = [], onCodeMirrorFocus, + settingsContent, + settingsTitle, }: SQLProps) => { let editor = useBlockNoteEditor(); const [results, setResults] = useState(null); const [queryCount, setQueryCount] = useState>(None); const [isFullscreen, setIsFullscreen] = useState(false); const [isFullscreenQueryCollapsed, setIsFullscreenQueryCollapsed] = useState(false); + const [settingsOpen, setSettingsOpen] = useState(false); const { incrementBadge, decrementBadge } = useContext(TabsContext); const execution = useBlockExecution(block.id); @@ -261,6 +273,16 @@ const SQL = ({ setName(text)} />
+ {settingsContent && ( + + + + )}
)} + + {/* Settings Modal */} + {settingsContent && ( + setSettingsOpen(false)} + size="sm" + > + + + {settingsTitle || "Settings"} + + + {settingsContent} + + + + )} ); }; diff --git a/src/lib/workflow/blocks/mysql.ts b/src/lib/workflow/blocks/mysql.ts index a90ba981..cef14162 100644 --- a/src/lib/workflow/blocks/mysql.ts +++ b/src/lib/workflow/blocks/mysql.ts @@ -5,17 +5,19 @@ export class MySqlBlock extends Block { query: string; uri: string; autoRefresh: number; + skipSqlModeInit: boolean; get typeName() { return "mysql"; } - constructor(id: string, name: string, dependency: DependencySpec, query: string, uri: string, autoRefresh: number) { + constructor(id: string, name: string, dependency: DependencySpec, query: string, uri: string, autoRefresh: number, skipSqlModeInit: boolean = false) { super(id, name, dependency); this.query = query; this.uri = uri; this.autoRefresh = autoRefresh; + this.skipSqlModeInit = skipSqlModeInit; } object() { @@ -25,6 +27,7 @@ export class MySqlBlock extends Block { query: this.query, uri: this.uri, autoRefresh: this.autoRefresh, + skipSqlModeInit: this.skipSqlModeInit, }; } @@ -34,6 +37,6 @@ export class MySqlBlock extends Block { static deserialize(json: string) { const data = JSON.parse(json); - return new MySqlBlock(data.id, data.name, data.dependency, data.query, data.uri, data.autoRefresh); + return new MySqlBlock(data.id, data.name, data.dependency, data.query, data.uri, data.autoRefresh, data.skipSqlModeInit ?? false); } } From 7cd8f9d8100889cfc6bc4f93609021d05952629d Mon Sep 17 00:00:00 2001 From: Ellie Huxtable Date: Tue, 20 Jan 2026 18:08:16 -0800 Subject: [PATCH 2/2] feat: move settings and fullscreen to top bar --- src/lib/blocks/common/SQL.tsx | 42 ++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/lib/blocks/common/SQL.tsx b/src/lib/blocks/common/SQL.tsx index 81963113..fcc7ec6b 100644 --- a/src/lib/blocks/common/SQL.tsx +++ b/src/lib/blocks/common/SQL.tsx @@ -266,32 +266,34 @@ const SQL = ({ type={block.typeName} setName={setName} inlineHeader + topRightElement={ +
+ {settingsContent && ( + + + + )} + + + +
+ } header={ <>

setName(text)} />

-
- {settingsContent && ( - - - - )} - - - -