From 90f99374262c485b61cb54f7cc4a025fc0ffe6c5 Mon Sep 17 00:00:00 2001 From: Ansgar Becker Date: Wed, 11 Mar 2026 17:09:21 +0100 Subject: [PATCH] feat: keep EXPLAIN output format traditional, on newer MySQL servers Refs #2423 --- source/dbstructures.mysql.pas | 5 +++++ source/dbstructures.pas | 2 +- source/main.pas | 18 +++++++++++------- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/source/dbstructures.mysql.pas b/source/dbstructures.mysql.pas index 5a0bcd62..100a8e09 100644 --- a/source/dbstructures.mysql.pas +++ b/source/dbstructures.mysql.pas @@ -3346,6 +3346,11 @@ begin ' WHERE'+ ' REFERENCED_TABLE_SCHEMA = :EscapedDatabase AND'+ ' REFERENCED_TABLE_NAME = :EscapedName'; + qExplain: Result := IfThen( + (FServerVersion >= 80400) and (FServerVersion < 100000), // Not MariaDB + 'EXPLAIN FORMAT=TRADITIONAL %s', + 'EXPLAIN %s' + ); else Result := inherited; end; end; diff --git a/source/dbstructures.pas b/source/dbstructures.pas index 6a62375f..72d2b84b 100644 --- a/source/dbstructures.pas +++ b/source/dbstructures.pas @@ -46,7 +46,7 @@ type qLockedTables, qDisableForeignKeyChecks, qEnableForeignKeyChecks, qOrderAsc, qOrderDesc, qGetRowCountExact, qGetRowCountApprox, qForeignKeyDrop, qGetTableColumns, qGetCollations, qGetCollationsExtended, qGetCharsets, - qGetReverseForeignKeys); + qGetReverseForeignKeys, qExplain); TSqlProvider = class strict protected FNetType: TNetType; diff --git a/source/main.pas b/source/main.pas index 5c752f9d..0eb9f9a7 100644 --- a/source/main.pas +++ b/source/main.pas @@ -3145,6 +3145,7 @@ end; procedure TMainForm.actExecuteQueryExecute(Sender: TObject); var ProfileNode: PVirtualNode; + Conn: TDBConnection; Batch: TSQLBatch; Tab: TQueryTab; BindParam: Integer; @@ -3154,11 +3155,12 @@ var ContainsUnsafeQueries, DoExecute: Boolean; begin Tab := QueryTabs.ActiveTab; + Conn := ActiveConnection; OperationRunning(True); DoExecute := True; ShowStatusMsg(_('Splitting SQL queries ...')); - Batch := TSQLBatch.Create(ActiveConnection.Parameters.NetTypeGroup); + Batch := TSQLBatch.Create(Conn.Parameters.NetTypeGroup); if Sender = actExecuteSelection then begin Batch.SQL := Tab.Memo.SelText; Tab.LeftOffsetInMemo := Tab.Memo.SelStart; @@ -3170,7 +3172,7 @@ begin ErrorDialog(_('Current query is empty'), _('Please move the cursor inside the query you want to use.')); DoExecute := False; end else begin - Batch.SQL := 'EXPLAIN ' + CurrentQuery; + Batch.SQL := Conn.SqlProvider.GetSql(qExplain, [CurrentQuery]); end; end else begin Batch.SQL := Tab.Memo.Text; @@ -3226,7 +3228,7 @@ begin ProfileNode := FindNode(Tab.treeHelpers, TQueryTab.HelperNodeProfile, nil); Tab.DoProfile := Assigned(ProfileNode) and (Tab.treeHelpers.CheckState[ProfileNode] in CheckedStates); if Tab.DoProfile then try - ActiveConnection.Query('SET profiling=1'); + Conn.Query('SET profiling=1'); except on E:EDbError do begin ErrorDialog(f_('Query profiling requires %s or later, and the server must not be configured with %s.', ['MySQL 5.0.37', '--disable-profiling']), E.Message); @@ -3236,9 +3238,9 @@ begin // Start the execution thread Screen.Cursor := crAppStart; - ActiveConnection.Ping(True); // Prevents SynEdit paint exceptions if connection was killed outside + Conn.Ping(True); // Prevents SynEdit paint exceptions if connection was killed outside Tab.QueryRunning := True; - Tab.ExecutionThread := TQueryThread.Create(ActiveConnection, Batch, Tab.Number); + Tab.ExecutionThread := TQueryThread.Create(Conn, Batch, Tab.Number); end; ValidateQueryControls(Sender); @@ -13713,15 +13715,17 @@ procedure TMainForm.lblExplainProcessClick(Sender: TObject); var Tab: TQueryTab; UsedDatabase: String; + Conn: TDBConnection; begin // Click on "Explain" link label, in process viewer + Conn := ActiveConnection; actNewQueryTabExecute(Sender); Tab := QueryTabs[QueryTabs.Count-1]; UsedDatabase := listProcesses.Text[listProcesses.FocusedNode, 3]; if not UsedDatabase.IsEmpty then begin - Tab.Memo.Lines.Add('USE ' + ActiveConnection.QuoteIdent(UsedDatabase) + ';'); + Tab.Memo.Lines.Add('USE ' + Conn.QuoteIdent(UsedDatabase) + ';'); end; - Tab.Memo.Lines.Add('EXPLAIN' + sLineBreak + SynMemoProcessView.Text + ';'); + Tab.Memo.Lines.Add(Conn.SqlProvider.GetSql(qExplain, [SynMemoProcessView.Text]) + ';'); Tab.TabSheet.Show; actExecuteQueryExecute(Sender); end;