mirror of
https://github.com/HeidiSQL/HeidiSQL.git
synced 2025-08-06 18:24:26 +08:00
* Bugfix: after an edit, a new row which did not match the filter was included in the grid.
* Bugfix: the entire width of all fields of edited columns were loaded, instead of a limited view. * Bugfix: (follow-up to above) one too many rows were included in RootNodeCount after less rows were matched than expected from the data source. * Bugfix: some memory was not released as early as it could've been when less rows were matched than expected from the data source. Hopefully fixes issue #730.
This commit is contained in:
@ -297,8 +297,9 @@ type
|
||||
procedure ShowTableProperties;
|
||||
procedure ShowTableData(table: WideString);
|
||||
procedure EnsureFullWidth(Grid: TBaseVirtualTree; Column: TColumnIndex; Node: PVirtualNode);
|
||||
procedure EnsureDataLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure DiscardData(Sender: TVirtualStringTree; Node: PVirtualNode);
|
||||
procedure EnsureNodeLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode; WhereClause: String);
|
||||
procedure EnsureChunkLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure DiscardNodeData(Sender: TVirtualStringTree; Node: PVirtualNode);
|
||||
procedure viewdata(Sender: TObject);
|
||||
procedure RefreshFieldListClick(Sender: TObject);
|
||||
procedure MenuRefreshClick(Sender: TObject);
|
||||
@ -538,7 +539,9 @@ type
|
||||
TablePropertiesForm : Ttbl_properties_form;
|
||||
FDataGridResult,
|
||||
FQueryGridResult : TGridResult;
|
||||
DataGridCurrentQuery : WideString;
|
||||
DataGridCurrentSelect : WideString;
|
||||
DataGridCurrentFilter : WideString;
|
||||
DataGridCurrentSort : WideString;
|
||||
|
||||
|
||||
procedure Init(AConn : POpenConnProf; AMysqlConn : TMysqlConn);
|
||||
@ -1419,14 +1422,9 @@ begin
|
||||
end;
|
||||
MainForm.ShowStatus( STATUS_MSG_READY );
|
||||
|
||||
sl_query.Clear;
|
||||
sl_query.Add( select_base );
|
||||
sl_query.Add(select_from);
|
||||
// Apply custom WHERE filter
|
||||
if Filter <> '' then sl_query.Add('WHERE ' + Filter);
|
||||
// Apply custom ORDER BY if detected in registry
|
||||
if sorting <> '' then sl_query.Add( sorting );
|
||||
DataGridCurrentQuery := sl_query.Text;
|
||||
DataGridCurrentSelect := select_base + select_from;
|
||||
DataGridCurrentFilter := Filter;
|
||||
DataGridCurrentSort := sorting;
|
||||
|
||||
SetLength(FDataGridResult.Rows, DataGrid.RootNodeCount);
|
||||
for i:=0 to DataGrid.RootNodeCount-1 do begin
|
||||
@ -3622,12 +3620,6 @@ begin
|
||||
end;
|
||||
|
||||
// Create instance of the progress form (but don't show it yet)
|
||||
// Todo: This apparently causes an exception if invoked via an event handler?
|
||||
// Classes.TStream.ReadComponent(???)
|
||||
// Classes.InternalReadComponentRes(???,???,???)
|
||||
// Classes.InitComponent(TfrmQueryProgress)
|
||||
// Classes.InitInheritedComponent($17E0710,TForm)
|
||||
// Forms.TCustomForm.Create(???)
|
||||
FProgressForm := TFrmQueryProgress.Create(Self);
|
||||
|
||||
{ Launch a thread of execution that passes the query to the server
|
||||
@ -5511,7 +5503,56 @@ begin
|
||||
end;
|
||||
|
||||
|
||||
procedure TMDIChild.EnsureDataLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
procedure TMDIChild.EnsureNodeLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode; WhereClause: String);
|
||||
var
|
||||
res: PGridResult;
|
||||
query: WideString;
|
||||
ds: TDataSet;
|
||||
i, j: LongInt;
|
||||
begin
|
||||
if Sender = DataGrid then res := @FDataGridResult
|
||||
else res := @FQueryGridResult;
|
||||
if (not res.Rows[Node.Index].Loaded) and (res.Rows[Node.Index].State <> grsInserted) then begin
|
||||
query := DataGridCurrentSelect;
|
||||
if DataGridCurrentFilter = '' then begin
|
||||
query := query + ' WHERE ' + WhereClause;
|
||||
end else begin
|
||||
query := query + ' WHERE (' + DataGridCurrentFilter + ') AND (' + WhereClause + ')';
|
||||
end;
|
||||
|
||||
// start query
|
||||
MainForm.ShowStatus('Retrieving data...');
|
||||
ds := GetResults(query);
|
||||
// If new data does not match current filter, remove from tree.
|
||||
if Cardinal(ds.RecordCount) < 1 then begin
|
||||
// Remove entry from dynamic array.
|
||||
for i := Node.Index to Length(res.Rows) - 1 do begin
|
||||
if i < Length(res.Rows) - 1 then res.Rows[i] := res.Rows[i + 1];
|
||||
end;
|
||||
SetLength(res.Rows, Length(res.Rows) - 1);
|
||||
// Remove entry from node list.
|
||||
Sender.DeleteNode(Node);
|
||||
end;
|
||||
|
||||
// fill in data
|
||||
MainForm.ShowStatus('Filling grid with record-data...');
|
||||
SetLength(res.Rows[Node.Index].Cells, ds.Fields.Count);
|
||||
i := Node.Index;
|
||||
for j := 0 to ds.Fields.Count - 1 do begin
|
||||
if res.Columns[j].IsBinary then
|
||||
res.Rows[i].Cells[j].Text := '0x' + BinToWideHex(ds.Fields[j].AsString)
|
||||
else
|
||||
res.Rows[i].Cells[j].Text := ds.Fields[j].AsWideString;
|
||||
res.Rows[i].Cells[j].IsNull := ds.Fields[j].IsNull;
|
||||
end;
|
||||
res.Rows[Node.Index].Loaded := True;
|
||||
|
||||
MainForm.ShowStatus( STATUS_MSG_READY );
|
||||
FreeAndNil(ds);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMDIChild.EnsureChunkLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode);
|
||||
var
|
||||
res: PGridResult;
|
||||
start, limit: Cardinal;
|
||||
@ -5523,40 +5564,42 @@ begin
|
||||
else res := @FQueryGridResult;
|
||||
if (not res.Rows[Node.Index].Loaded) and (res.Rows[Node.Index].State <> grsInserted) then begin
|
||||
start := Node.Index - (Node.Index mod GridMaxRows);
|
||||
limit := DataGrid.RootNodeCount - start;
|
||||
limit := TVirtualStringTree(Sender).RootNodeCount - start;
|
||||
if limit > GridMaxRows then limit := GridMaxRows;
|
||||
query := DataGridCurrentQuery + WideFormat(' LIMIT %d, %d', [start, limit]);
|
||||
query := DataGridCurrentSelect;
|
||||
if DataGridCurrentFilter <> '' then query := query + ' WHERE ' + DataGridCurrentFilter;
|
||||
query := query + DataGridCurrentSort + WideFormat(' LIMIT %d, %d', [start, limit]);
|
||||
|
||||
// start query
|
||||
MainForm.ShowStatus('Retrieving data...');
|
||||
ds := GetResults(query);
|
||||
if Cardinal(ds.RecordCount) < limit then begin
|
||||
limit := ds.RecordCount;
|
||||
DataGrid.RootNodeCount := start + limit + 1;
|
||||
TVirtualStringTree(Sender).RootNodeCount := start + limit;
|
||||
SetLength(res.Rows, start + limit);
|
||||
end;
|
||||
|
||||
// fill in data
|
||||
MainForm.ShowStatus('Filling grid with record-data...');
|
||||
for i := start to start + limit - 1 do begin
|
||||
SetLength(FDataGridResult.Rows[i].Cells, ds.Fields.Count);
|
||||
SetLength(res.Rows[i].Cells, ds.Fields.Count);
|
||||
for j := 0 to ds.Fields.Count - 1 do begin
|
||||
if FDataGridResult.Columns[j].IsBinary then
|
||||
FDataGridResult.Rows[i].Cells[j].Text := '0x' + BinToWideHex(ds.Fields[j].AsString)
|
||||
if res.Columns[j].IsBinary then
|
||||
res.Rows[i].Cells[j].Text := '0x' + BinToWideHex(ds.Fields[j].AsString)
|
||||
else
|
||||
FDataGridResult.Rows[i].Cells[j].Text := ds.Fields[j].AsWideString;
|
||||
FDataGridResult.Rows[i].Cells[j].IsNull := ds.Fields[j].IsNull;
|
||||
res.Rows[i].Cells[j].Text := ds.Fields[j].AsWideString;
|
||||
res.Rows[i].Cells[j].IsNull := ds.Fields[j].IsNull;
|
||||
end;
|
||||
FDataGridResult.Rows[i].Loaded := True;
|
||||
res.Rows[i].Loaded := True;
|
||||
ds.Next;
|
||||
end;
|
||||
|
||||
MainForm.ShowStatus( STATUS_MSG_READY );
|
||||
// Todo: Seen an AV next line when this method was invoked via an event handler.
|
||||
FreeAndNil(ds);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TMDIChild.DiscardData(Sender: TVirtualStringTree; Node: PVirtualNode);
|
||||
procedure TMDIChild.DiscardNodeData(Sender: TVirtualStringTree; Node: PVirtualNode);
|
||||
var
|
||||
Data: PGridResult;
|
||||
begin
|
||||
@ -5585,9 +5628,9 @@ begin
|
||||
Exit;
|
||||
if Sender = DataGrid then gr := @FDataGridResult
|
||||
else gr := @FQueryGridResult;
|
||||
if Node.Index >= Cardinal(Length(gr.Rows)) then
|
||||
Exit;
|
||||
EnsureDataLoaded(Sender, Node);
|
||||
if Node.Index >= Cardinal(Length(gr.Rows)) then Exit;
|
||||
EnsureChunkLoaded(Sender, Node);
|
||||
if Node.Index >= Cardinal(Length(gr.Rows)) then Exit;
|
||||
c := @gr.Rows[Node.Index].Cells[Column];
|
||||
EditingCell := Sender.IsEditing and (Node = Sender.FocusedNode) and (Column = Sender.FocusedColumn);
|
||||
if c.Modified then begin
|
||||
@ -5675,8 +5718,8 @@ procedure TMDIChild.DataGridAfterCellPaint(Sender: TBaseVirtualTree;
|
||||
CellRect: TRect);
|
||||
begin
|
||||
// Don't waist time
|
||||
if Column = -1 then
|
||||
Exit;
|
||||
if Column = -1 then Exit;
|
||||
if Node.Index >= Cardinal(Length(FDataGridResult.Rows)) then Exit;
|
||||
// Paint a red triangle at the top left corner of the cell
|
||||
if FDataGridResult.Rows[Node.Index].Cells[Column].Modified then
|
||||
Mainform.PngImageListMain.Draw(TargetCanvas, CellRect.Left, CellRect.Top, 111);
|
||||
@ -5813,7 +5856,6 @@ var
|
||||
i: Integer;
|
||||
sql, Val: WideString;
|
||||
Row: PGridRow;
|
||||
ds: TDataSet;
|
||||
begin
|
||||
sql := 'UPDATE '+mask(SelectedTable)+' SET';
|
||||
Row := @FDataGridResult.Rows[Sender.FocusedNode.Index];
|
||||
@ -5849,28 +5891,8 @@ begin
|
||||
Row.Cells[i].IsNull := Row.Cells[i].NewIsNull;
|
||||
end;
|
||||
GridFinalizeEditing(Sender);
|
||||
sql := 'SELECT ';
|
||||
for i := 0 to Length(FDataGridResult.Columns) - 1 do
|
||||
sql := sql + mask(FDataGridResult.Columns[i].Name) + ', ';
|
||||
// Cut trailing comma
|
||||
sql := Copy(sql, 1, Length(sql)-2);
|
||||
sql := sql + ' FROM ' + mask(SelectedTable)
|
||||
+ ' WHERE ' + GetWhereClause(Row, @FDataGridResult.Columns, FSelectedTableKeys);
|
||||
ds := ExecSelectQuery(sql);
|
||||
if ds.RecordCount = 1 then begin
|
||||
for i := 0 to ds.FieldCount - 1 do begin
|
||||
if FDataGridResult.Columns[i].IsBinary then
|
||||
Row.Cells[i].Text := '0x' + BinToWideHex(ds.Fields[i].AsString)
|
||||
else
|
||||
Row.Cells[i].Text := ds.Fields[i].AsWideString;
|
||||
Row.Cells[i].IsNull := ds.Fields[i].IsNull;
|
||||
end;
|
||||
Sender.RepaintNode(Sender.FocusedNode);
|
||||
end else begin
|
||||
logsql('Unable to identify updated row, found '+FormatNumber(ds.RecordCount)+' identical row(s). Doing full reload.');
|
||||
viewdata(Sender);
|
||||
end;
|
||||
ds.Free;
|
||||
Row.Loaded := false;
|
||||
EnsureNodeLoaded(Sender, Sender.FocusedNode, GetWhereClause(Row, @FDataGridResult.Columns, FSelectedTableKeys));
|
||||
end;
|
||||
end;
|
||||
|
||||
@ -6019,14 +6041,12 @@ begin
|
||||
Vals := Copy(Vals, 1, Length(Vals)-2);
|
||||
Cols := Copy(Cols, 1, Length(Cols)-2);
|
||||
sql := 'INSERT INTO '+mask(SelectedTable)+' ('+Cols+') VALUES ('+Vals+')';
|
||||
try
|
||||
// Send INSERT query
|
||||
ExecUpdateQuery(sql, False, True);
|
||||
Result := True;
|
||||
GridFinalizeEditing(Sender);
|
||||
except
|
||||
Result := False;
|
||||
end;
|
||||
// Send INSERT query
|
||||
ExecUpdateQuery(sql, False, True);
|
||||
Result := True;
|
||||
Row.Loaded := false;
|
||||
EnsureNodeLoaded(Sender, Node, GetWhereClause(Row, @FDataGridResult.Columns, FSelectedTableKeys));
|
||||
GridFinalizeEditing(Sender);
|
||||
end;
|
||||
end;
|
||||
|
||||
|
@ -837,7 +837,7 @@ begin
|
||||
if not (coVisible in Grid.Header.Columns[i].Options) then
|
||||
Continue;
|
||||
// Ensure basic data is loaded and load remainder of large fields.
|
||||
Mainform.Childwin.EnsureDataLoaded(Grid, Node);
|
||||
Mainform.Childwin.EnsureChunkLoaded(Grid, Node);
|
||||
Mainform.Childwin.EnsureFullWidth(Grid, i, Node);
|
||||
Data := Grid.Text[Node, i];
|
||||
// Handle nulls.
|
||||
@ -849,7 +849,7 @@ begin
|
||||
tmp := tmp + ' </tr>' + CRLF;
|
||||
StreamWrite(S, tmp);
|
||||
// Release some memory.
|
||||
Mainform.Childwin.DiscardData(Grid, Node);
|
||||
Mainform.Childwin.DiscardNodeData(Grid, Node);
|
||||
Node := Grid.GetNext(Node);
|
||||
end;
|
||||
// footer:
|
||||
@ -915,7 +915,7 @@ begin
|
||||
if not (coVisible in Grid.Header.Columns[i].Options) then
|
||||
Continue;
|
||||
// Ensure basic data is loaded and load remainder of large fields.
|
||||
Mainform.Childwin.EnsureDataLoaded(Grid, Node);
|
||||
Mainform.Childwin.EnsureChunkLoaded(Grid, Node);
|
||||
Mainform.Childwin.EnsureFullWidth(Grid, i, Node);
|
||||
Data := Grid.Text[Node, i];
|
||||
// Remove 0x.
|
||||
@ -934,7 +934,7 @@ begin
|
||||
tmp := tmp + Terminator;
|
||||
StreamWrite(S, tmp);
|
||||
// Release some memory.
|
||||
Mainform.Childwin.DiscardData(Grid, Node);
|
||||
Mainform.Childwin.DiscardNodeData(Grid, Node);
|
||||
Node := Grid.GetNext(Node);
|
||||
end;
|
||||
Grid.Visible := true;
|
||||
@ -973,7 +973,7 @@ begin
|
||||
// Print cell start tag.
|
||||
tmp := tmp + #9#9'<' + Grid.Header.Columns[i].Text;
|
||||
// Ensure basic data is loaded.
|
||||
Mainform.Childwin.EnsureDataLoaded(Grid, Node);
|
||||
Mainform.Childwin.EnsureChunkLoaded(Grid, Node);
|
||||
if GridData.Rows[Node.Index].Cells[i].IsNull then tmp := tmp + ' isnull="true" />' + CRLF
|
||||
else begin
|
||||
if GridData.Columns[i].IsBinary then tmp := tmp + ' format="hex"';
|
||||
@ -994,7 +994,7 @@ begin
|
||||
tmp := tmp + #9'</row>' + CRLF;
|
||||
StreamWrite(S, tmp);
|
||||
// Release some memory.
|
||||
Mainform.Childwin.DiscardData(Grid, Node);
|
||||
Mainform.Childwin.DiscardNodeData(Grid, Node);
|
||||
Node := Grid.GetNext(Node);
|
||||
end;
|
||||
// footer:
|
||||
|
Reference in New Issue
Block a user