mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-26 03:01:07 +08:00
Add a toolbar button which, when pressed, allows BLOBs to be displayed as text. Explicitly ignoring weird effects in grid updates/inserts. Fixes issue #1624.
This commit is contained in:
@ -99,6 +99,8 @@ const
|
||||
REGNAME_QUERYHELPERSWIDTH = 'queryhelperswidth';
|
||||
REGNAME_STOPONERRORSINBATCH = 'StopOnErrorsInBatchMode';
|
||||
DEFAULT_STOPONERRORSINBATCH = True;
|
||||
REGNAME_BLOBASTEXT = 'DisplayBLOBsAsText';
|
||||
DEFAULT_BLOBASTEXT = False;
|
||||
REGNAME_EDITOR_WIDTH = 'MemoEditorWidth';
|
||||
DEFAULT_EDITOR_WIDTH = 100;
|
||||
REGNAME_EDITOR_HEIGHT = 'MemoEditorHeight';
|
||||
|
@ -986,7 +986,8 @@ begin
|
||||
Continue;
|
||||
Data := GridData.Columns[i].Name;
|
||||
// Alter column name in header if data is not raw.
|
||||
if GridData.Columns[i].DatatypeCat = dtcBinary then Data := 'HEX(' + Data + ')';
|
||||
if (GridData.Columns[i].DatatypeCat = dtcBinary) and (not Mainform.actBlobAsText.Checked) then
|
||||
Data := 'HEX(' + Data + ')';
|
||||
// Add header item.
|
||||
if tmp <> '' then tmp := tmp + Separator;
|
||||
tmp := tmp + Encloser + Data + Encloser;
|
||||
@ -1010,7 +1011,8 @@ begin
|
||||
Continue;
|
||||
Data := Grid.Text[Node, i];
|
||||
// Remove 0x.
|
||||
if GridData.Columns[i].DatatypeCat = dtcBinary then Delete(Data, 1, 2);
|
||||
if (GridData.Columns[i].DatatypeCat = dtcBinary) and (not Mainform.actBlobAsText.Checked) then
|
||||
Delete(Data, 1, 2);
|
||||
// Unformat numeric values
|
||||
if (GridData.Columns[i].DatatypeCat in [dtcInteger, dtcReal]) and (not Mainform.prefExportLocaleNumbers) then
|
||||
Data := UnformatNumber(Data);
|
||||
@ -1093,11 +1095,13 @@ begin
|
||||
tmp := tmp + #9#9'<' + Grid.Header.Columns[i].Text;
|
||||
if GridData.Rows[Node.Index].Cells[i].IsNull then tmp := tmp + ' isnull="true" />' + CRLF
|
||||
else begin
|
||||
if GridData.Columns[i].DatatypeCat = dtcBinary then tmp := tmp + ' format="hex"';
|
||||
if (GridData.Columns[i].DatatypeCat = dtcBinary) and (not Mainform.actBlobAsText.Checked) then
|
||||
tmp := tmp + ' format="hex"';
|
||||
tmp := tmp + '>';
|
||||
Data := Grid.Text[Node, i];
|
||||
// Remove 0x.
|
||||
if GridData.Columns[i].DatatypeCat = dtcBinary then Delete(Data, 1, 2);
|
||||
if (GridData.Columns[i].DatatypeCat = dtcBinary) and (not Mainform.actBlobAsText.Checked) then
|
||||
Delete(Data, 1, 2);
|
||||
// Unformat numeric values
|
||||
if (GridData.Columns[i].DatatypeCat in [dtcInteger, dtcReal]) and (not Mainform.prefExportLocaleNumbers) then
|
||||
Data := UnformatNumber(Data);
|
||||
@ -1184,7 +1188,8 @@ begin
|
||||
else begin
|
||||
Data := Grid.Text[Node, i];
|
||||
// Remove 0x.
|
||||
if GridData.Columns[i].DatatypeCat = dtcBinary then Delete(Data, 1, 2);
|
||||
if (GridData.Columns[i].DatatypeCat = dtcBinary) and (not Mainform.actBlobAsText.Checked) then
|
||||
Delete(Data, 1, 2);
|
||||
// Unformat numeric values
|
||||
if GridData.Columns[i].DatatypeCat in [dtcInteger, dtcReal] then
|
||||
tmp := tmp + UnformatNumber(Data)
|
||||
|
@ -252,7 +252,7 @@ object MainForm: TMainForm
|
||||
object ToolBarQuery: TToolBar
|
||||
Left = 494
|
||||
Top = 2
|
||||
Width = 243
|
||||
Width = 268
|
||||
Height = 22
|
||||
Align = alNone
|
||||
AutoSize = True
|
||||
@ -304,13 +304,18 @@ object MainForm: TMainForm
|
||||
Top = 0
|
||||
Action = actQueryStopOnErrors
|
||||
end
|
||||
object btnBlobAsText: TToolButton
|
||||
Left = 199
|
||||
Top = 0
|
||||
Action = actBlobAsText
|
||||
end
|
||||
object btnQueryWordwrap: TToolButton
|
||||
Left = 197
|
||||
Left = 222
|
||||
Top = 0
|
||||
Action = actQueryWordWrap
|
||||
end
|
||||
object btnSetDelimiter: TToolButton
|
||||
Left = 220
|
||||
Left = 245
|
||||
Top = 0
|
||||
Action = actSetDelimiter
|
||||
end
|
||||
@ -2290,6 +2295,14 @@ object MainForm: TMainForm
|
||||
ShortCut = 16503
|
||||
OnExecute = actReformatSQLExecute
|
||||
end
|
||||
object actBlobAsText: TAction
|
||||
Category = 'Data'
|
||||
AutoCheck = True
|
||||
Caption = 'View binary data as text (instead of HEX)'
|
||||
Hint = 'View binary data as text (instead of HEX)'
|
||||
ImageIndex = 141
|
||||
OnExecute = actBlobAsTextExecute
|
||||
end
|
||||
end
|
||||
object SaveDialog2: TSaveDialog
|
||||
DefaultExt = 'reg'
|
||||
@ -6196,6 +6209,28 @@ object MainForm: TMainForm
|
||||
D071B9192663E11631D90D5EAFD79F208009C672CFAAF24282114419A248F75E
|
||||
2627C13AF8E0CC1BFB6BEBD07FAE35DDF92001CCFD01229E70157CD3A2DA0000
|
||||
000049454E44AE426082}
|
||||
end
|
||||
item
|
||||
Background = clWindow
|
||||
Name = 'page_white_text_hex'
|
||||
PngImage.Data = {
|
||||
89504E470D0A1A0A0000000D49484452000000100000001008060000001FF3FF
|
||||
610000001974455874536F667477617265005061696E742E4E45542076332E35
|
||||
2E32D7EE6943000001BF4944415478DA85934D48025110C7673F72430841C12E
|
||||
75EA5474CABE5B254FD1AD4B089E8A0E520A1174EAE35479953C75B08B201481
|
||||
509708F2D0E75A128174C953D62DEFA1BBBAF6E6B56F59C1B5816186B7F3FFCD
|
||||
BCDD1D0EFEAC8F782F71013ADB37F14FE23A3BE08CE8AB56AB3941107A388EE3
|
||||
DB29EBF53AA452A9642C164B58210C30AE699A52ABD578026811E9BA0EAAAA82
|
||||
C7E3814AA502D96C36198D464D086740C648F1138100CFF354C4008D468302DC
|
||||
6E378DF82C93C924239108423E5A0058AC280A2D444720F35028D47225511427
|
||||
4828B4009ACD26B02B608E40749C0421D81D73AFD7DB1E80C242A1408BB110A7
|
||||
60D740474030180497CB650F60B627CED0B8A3DD9B628C3899D3E9B407148B45
|
||||
381F5985B9C704155CFB3721908B53214264590687C3D17902ECBE5B7F30739C
|
||||
62BF4B86ADDA2DC4A5007D660B28954A703AB40C0BAF47B4E3856F0DE6F38770
|
||||
39B94EA7BA9ADEE80CB07645C3CEDBEA1DCD0F1C7E9AE3BF620B2897CB901E08
|
||||
43F83D4D2738195C82C5B763381B5E31A3DD0479CBAF6D7E05EBBBC0DC883A01
|
||||
4C91E3672618257B704396A99BE46D97C9623AF93A3F9224CD92FC8501FA8D75
|
||||
FE4FCCAC61ACF6D72F62B02F294EFE3B9F0000000049454E44AE426082}
|
||||
end>
|
||||
PngOptions = [pngBlendOnDisabled, pngGrayscaleOnDisabled]
|
||||
Left = 104
|
||||
|
@ -452,6 +452,8 @@ type
|
||||
ReformatSQL2: TMenuItem;
|
||||
menuQueryInsertFunction: TMenuItem;
|
||||
menuFilterInsertFunction: TMenuItem;
|
||||
actBlobAsText: TAction;
|
||||
btnBlobAsText: TToolButton;
|
||||
procedure refreshMonitorConfig;
|
||||
procedure loadWindowConfig;
|
||||
procedure saveWindowConfig;
|
||||
@ -719,6 +721,7 @@ type
|
||||
procedure DBtreeFocusChanging(Sender: TBaseVirtualTree; OldNode,
|
||||
NewNode: PVirtualNode; OldColumn, NewColumn: TColumnIndex;
|
||||
var Allowed: Boolean);
|
||||
procedure actBlobAsTextExecute(Sender: TObject);
|
||||
private
|
||||
ReachedEOT: Boolean;
|
||||
FDelimiter: String;
|
||||
@ -755,6 +758,7 @@ type
|
||||
procedure SaveQueryMemo(Tab: TQueryTab; Filename: String; OnlySelection: Boolean);
|
||||
procedure UpdateFilterPanel(Sender: TObject);
|
||||
procedure DatabaseChanged(Database: String);
|
||||
function GetBlobContent(Results: TMySQLQuery; Column: Integer): String;
|
||||
public
|
||||
Connection: TMySQLConnection;
|
||||
SessionName: String;
|
||||
@ -1100,6 +1104,7 @@ begin
|
||||
MainReg.WriteInteger(REGNAME_TOOLBARQUERYLEFT, ToolBarQuery.Left);
|
||||
MainReg.WriteInteger(REGNAME_TOOLBARQUERYTOP, ToolBarQuery.Top);
|
||||
MainReg.WriteBool(REGNAME_STOPONERRORSINBATCH, actQueryStopOnErrors.Checked);
|
||||
MainReg.WriteBool(REGNAME_BLOBASTEXT, actBlobAsText.Checked);
|
||||
|
||||
// Save delimiter
|
||||
MainReg.WriteString( REGNAME_DELIMITER, Delimiter );
|
||||
@ -1241,6 +1246,7 @@ begin
|
||||
ToolBarQuery.Left := GetRegValue(REGNAME_TOOLBARQUERYLEFT, ToolBarQuery.Left);
|
||||
ToolBarQuery.Top := GetRegValue(REGNAME_TOOLBARQUERYTOP, ToolBarQuery.Top);
|
||||
actQueryStopOnErrors.Checked := GetRegValue(REGNAME_STOPONERRORSINBATCH, DEFAULT_STOPONERRORSINBATCH);
|
||||
actBlobAsText.Checked := GetRegValue(REGNAME_BLOBASTEXT, DEFAULT_BLOBASTEXT);
|
||||
|
||||
pnlQueryMemo.Height := GetRegValue(REGNAME_QUERYMEMOHEIGHT, pnlQueryMemo.Height);
|
||||
pnlQueryHelpers.Width := GetRegValue(REGNAME_QUERYHELPERSWIDTH, pnlQueryHelpers.Width);
|
||||
@ -3935,7 +3941,7 @@ begin
|
||||
for j:=0 to Results.ColumnCount-1 do begin
|
||||
case ActiveGridResult.Columns[j].DatatypeCat of
|
||||
dtcInteger, dtcReal: ActiveGridResult.Rows[i].Cells[j].Text := FormatNumber(Results.Col(j), False);
|
||||
dtcBinary: ActiveGridResult.Rows[i].Cells[j].Text := '0x' + Results.BinColAsHex(j);
|
||||
dtcBinary: ActiveGridResult.Rows[i].Cells[j].Text := GetBlobContent(Results, j);
|
||||
else ActiveGridResult.Rows[i].Cells[j].Text := Results.Col(j);
|
||||
end;
|
||||
ActiveGridResult.Rows[i].Cells[j].IsNull := Results.IsNull(j);
|
||||
@ -6443,7 +6449,7 @@ begin
|
||||
for j := 0 to Results.ColumnCount - 1 do begin
|
||||
case res.Columns[j].DatatypeCat of
|
||||
dtcInteger, dtcReal: res.Rows[i].Cells[j].Text := FormatNumber(Results.Col(j), False);
|
||||
dtcBinary: res.Rows[i].Cells[j].Text := '0x' + Results.BinColAsHex(j);
|
||||
dtcBinary: res.Rows[i].Cells[j].Text := GetBlobContent(Results, j);
|
||||
else res.Rows[i].Cells[j].Text := Results.Col(j);
|
||||
end;
|
||||
res.Rows[i].Cells[j].IsNull := Results.IsNull(j);
|
||||
@ -6519,7 +6525,7 @@ begin
|
||||
for j:=0 to Results.ColumnCount-1 do begin
|
||||
case res.Columns[j].DatatypeCat of
|
||||
dtcInteger, dtcReal: res.Rows[i].Cells[j].Text := FormatNumber(Results.Col(j), False);
|
||||
dtcBinary: res.Rows[i].Cells[j].Text := '0x' + Results.BinColAsHex(j);
|
||||
dtcBinary: res.Rows[i].Cells[j].Text := GetBlobContent(Results, j);
|
||||
else res.Rows[i].Cells[j].Text := Results.Col(j);
|
||||
end;
|
||||
res.Rows[i].Cells[j].IsNull := Results.IsNull(j);
|
||||
@ -6812,8 +6818,13 @@ begin
|
||||
case DataGridResult.Columns[i].DatatypeCat of
|
||||
dtcInteger, dtcReal: Val := UnformatNumber(Val);
|
||||
dtcBinary: begin
|
||||
CheckHex(Copy(Val, 3), 'Invalid hexadecimal string given in field "' + DataGridResult.Columns[i].Name + '".');
|
||||
if Val = '0x' then Val := esc('');
|
||||
if actBlobAsText.Checked then
|
||||
Val := esc(Val)
|
||||
else begin
|
||||
CheckHex(Copy(Val, 3), 'Invalid hexadecimal string given in field "' + DataGridResult.Columns[i].Name + '".');
|
||||
if Val = '0x' then
|
||||
Val := esc('');
|
||||
end;
|
||||
end;
|
||||
else Val := esc(Val);
|
||||
end;
|
||||
@ -6901,7 +6912,12 @@ begin
|
||||
// Quote if needed
|
||||
case DataGridResult.Columns[j].DatatypeCat of
|
||||
dtcInteger, dtcReal: KeyVal := UnformatNumber(KeyVal);
|
||||
dtcBinary: if KeyVal = '0x' then KeyVal := esc('');
|
||||
dtcBinary: begin
|
||||
if actBlobAsText.Checked then
|
||||
KeyVal := esc(KeyVal)
|
||||
else if KeyVal = '0x' then
|
||||
KeyVal := esc('');
|
||||
end
|
||||
else KeyVal := esc(KeyVal);
|
||||
end;
|
||||
|
||||
@ -7022,9 +7038,13 @@ begin
|
||||
case DataGridResult.Columns[i].DatatypeCat of
|
||||
dtcInteger, dtcReal: Val := UnformatNumber(Val);
|
||||
dtcBinary: begin
|
||||
CheckHex(Copy(Val, 3), 'Invalid hexadecimal string given in field "' + DataGridResult.Columns[i].Name + '".');
|
||||
if Val = '0x' then
|
||||
Val := esc('');
|
||||
if actBlobAsText.Checked then
|
||||
Val := esc(Val)
|
||||
else begin
|
||||
CheckHex(Copy(Val, 3), 'Invalid hexadecimal string given in field "' + DataGridResult.Columns[i].Name + '".');
|
||||
if Val = '0x' then
|
||||
Val := esc('');
|
||||
end;
|
||||
end;
|
||||
else Val := esc(Val);
|
||||
end;
|
||||
@ -7209,7 +7229,7 @@ begin
|
||||
Cell := @DataGridResult.Rows[Node.Index].Cells[Column];
|
||||
len := Length(Cell.Text);
|
||||
// Recalculate due to textual formatting of raw binary data.
|
||||
if (Col.DatatypeCat = dtcBinary) and (len > 2) then len := (len - 2) div 2;
|
||||
if (Col.DatatypeCat = dtcBinary) and (not actBlobAsText.Checked) and (len > 2) then len := (len - 2) div 2;
|
||||
// Assume width limit in effect if data exactly at limit threshold.
|
||||
if len = GridMaxData then begin
|
||||
if CheckUniqueKeyClause then begin
|
||||
@ -7221,7 +7241,7 @@ begin
|
||||
Results := Connection.GetResults(sql);
|
||||
case Col.DatatypeCat of
|
||||
dtcInteger, dtcReal: Cell.Text := FormatNumber(Results.Col(0), False);
|
||||
dtcBinary: Cell.Text := '0x' + Results.BinColAsHex(0);
|
||||
dtcBinary: Cell.Text := GetBlobContent(Results, 0);
|
||||
else Cell.Text := Results.Col(0);
|
||||
end;
|
||||
Cell.IsNull := Results.IsNull(0);
|
||||
@ -7275,7 +7295,7 @@ var
|
||||
begin
|
||||
VT := Sender as TVirtualStringTree;
|
||||
TypeCat := DataGridResult.Columns[Column].DatatypeCat;
|
||||
if TypeCat = dtcText then begin
|
||||
if (TypeCat = dtcText) or ((TypeCat = dtcBinary) and actBlobAsText.Checked) then begin
|
||||
InplaceEditor := TInplaceEditorLink.Create(VT);
|
||||
InplaceEditor.DataType := DataGridResult.Columns[Column].Datatype;
|
||||
InplaceEditor.MaxLength := DataGridResult.Columns[Column].MaxLength;
|
||||
@ -9111,5 +9131,21 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TMainForm.actBlobAsTextExecute(Sender: TObject);
|
||||
begin
|
||||
// Activate displaying BLOBs as text data, ignoring possible weird effects in grid updates/inserts
|
||||
if PageControlMain.ActivePage = tabData then
|
||||
viewdata(Sender);
|
||||
end;
|
||||
|
||||
|
||||
function TMainForm.GetBlobContent(Results: TMySQLQuery; Column: Integer): String;
|
||||
begin
|
||||
if actBlobAsText.Checked then
|
||||
Result := Results.Col(Column)
|
||||
else
|
||||
Result := '0x' + Results.BinColAsHex(Column);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
||||
|
@ -1199,14 +1199,10 @@ end;
|
||||
function TMySQLQuery.Col(Column: Integer; IgnoreErrors: Boolean=False): String;
|
||||
begin
|
||||
if (Column > -1) and (Column < ColumnCount) then begin
|
||||
if FDatatypes[Column].Category = dtcBinary then
|
||||
Raise Exception.CreateFmt('Column "%s" has binary collation. Please use BinColAsHex() instead Col().', [FColumnNames[Column]])
|
||||
else begin
|
||||
if Connection.IsUnicode then
|
||||
Result := UTF8ToString(FCurrentRow[Column])
|
||||
else
|
||||
Result := String(FCurrentRow[Column]);
|
||||
end;
|
||||
if Connection.IsUnicode then
|
||||
Result := UTF8ToString(FCurrentRow[Column])
|
||||
else
|
||||
Result := String(FCurrentRow[Column]);
|
||||
end else if not IgnoreErrors then
|
||||
Raise Exception.CreateFmt('Column #%d not available. Query returned %d columns and %d rows.', [Column, ColumnCount, RecordCount]);
|
||||
end;
|
||||
|
Reference in New Issue
Block a user