* 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:
rosenfield.albert
2008-09-08 16:09:20 +00:00
parent be23b392ae
commit 4efb511b95
2 changed files with 91 additions and 71 deletions

View File

@ -297,8 +297,9 @@ type
procedure ShowTableProperties; procedure ShowTableProperties;
procedure ShowTableData(table: WideString); procedure ShowTableData(table: WideString);
procedure EnsureFullWidth(Grid: TBaseVirtualTree; Column: TColumnIndex; Node: PVirtualNode); procedure EnsureFullWidth(Grid: TBaseVirtualTree; Column: TColumnIndex; Node: PVirtualNode);
procedure EnsureDataLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode); procedure EnsureNodeLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode; WhereClause: String);
procedure DiscardData(Sender: TVirtualStringTree; Node: PVirtualNode); procedure EnsureChunkLoaded(Sender: TBaseVirtualTree; Node: PVirtualNode);
procedure DiscardNodeData(Sender: TVirtualStringTree; Node: PVirtualNode);
procedure viewdata(Sender: TObject); procedure viewdata(Sender: TObject);
procedure RefreshFieldListClick(Sender: TObject); procedure RefreshFieldListClick(Sender: TObject);
procedure MenuRefreshClick(Sender: TObject); procedure MenuRefreshClick(Sender: TObject);
@ -538,7 +539,9 @@ type
TablePropertiesForm : Ttbl_properties_form; TablePropertiesForm : Ttbl_properties_form;
FDataGridResult, FDataGridResult,
FQueryGridResult : TGridResult; FQueryGridResult : TGridResult;
DataGridCurrentQuery : WideString; DataGridCurrentSelect : WideString;
DataGridCurrentFilter : WideString;
DataGridCurrentSort : WideString;
procedure Init(AConn : POpenConnProf; AMysqlConn : TMysqlConn); procedure Init(AConn : POpenConnProf; AMysqlConn : TMysqlConn);
@ -1419,14 +1422,9 @@ begin
end; end;
MainForm.ShowStatus( STATUS_MSG_READY ); MainForm.ShowStatus( STATUS_MSG_READY );
sl_query.Clear; DataGridCurrentSelect := select_base + select_from;
sl_query.Add( select_base ); DataGridCurrentFilter := Filter;
sl_query.Add(select_from); DataGridCurrentSort := sorting;
// 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;
SetLength(FDataGridResult.Rows, DataGrid.RootNodeCount); SetLength(FDataGridResult.Rows, DataGrid.RootNodeCount);
for i:=0 to DataGrid.RootNodeCount-1 do begin for i:=0 to DataGrid.RootNodeCount-1 do begin
@ -3622,12 +3620,6 @@ begin
end; end;
// Create instance of the progress form (but don't show it yet) // 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); FProgressForm := TFrmQueryProgress.Create(Self);
{ Launch a thread of execution that passes the query to the server { Launch a thread of execution that passes the query to the server
@ -5511,7 +5503,56 @@ begin
end; 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 var
res: PGridResult; res: PGridResult;
start, limit: Cardinal; start, limit: Cardinal;
@ -5523,40 +5564,42 @@ begin
else res := @FQueryGridResult; else res := @FQueryGridResult;
if (not res.Rows[Node.Index].Loaded) and (res.Rows[Node.Index].State <> grsInserted) then begin if (not res.Rows[Node.Index].Loaded) and (res.Rows[Node.Index].State <> grsInserted) then begin
start := Node.Index - (Node.Index mod GridMaxRows); start := Node.Index - (Node.Index mod GridMaxRows);
limit := DataGrid.RootNodeCount - start; limit := TVirtualStringTree(Sender).RootNodeCount - start;
if limit > GridMaxRows then limit := GridMaxRows; 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 // start query
MainForm.ShowStatus('Retrieving data...'); MainForm.ShowStatus('Retrieving data...');
ds := GetResults(query); ds := GetResults(query);
if Cardinal(ds.RecordCount) < limit then begin if Cardinal(ds.RecordCount) < limit then begin
limit := ds.RecordCount; limit := ds.RecordCount;
DataGrid.RootNodeCount := start + limit + 1; TVirtualStringTree(Sender).RootNodeCount := start + limit;
SetLength(res.Rows, start + limit);
end; end;
// fill in data // fill in data
MainForm.ShowStatus('Filling grid with record-data...'); MainForm.ShowStatus('Filling grid with record-data...');
for i := start to start + limit - 1 do begin 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 for j := 0 to ds.Fields.Count - 1 do begin
if FDataGridResult.Columns[j].IsBinary then if res.Columns[j].IsBinary then
FDataGridResult.Rows[i].Cells[j].Text := '0x' + BinToWideHex(ds.Fields[j].AsString) res.Rows[i].Cells[j].Text := '0x' + BinToWideHex(ds.Fields[j].AsString)
else else
FDataGridResult.Rows[i].Cells[j].Text := ds.Fields[j].AsWideString; res.Rows[i].Cells[j].Text := ds.Fields[j].AsWideString;
FDataGridResult.Rows[i].Cells[j].IsNull := ds.Fields[j].IsNull; res.Rows[i].Cells[j].IsNull := ds.Fields[j].IsNull;
end; end;
FDataGridResult.Rows[i].Loaded := True; res.Rows[i].Loaded := True;
ds.Next; ds.Next;
end; end;
MainForm.ShowStatus( STATUS_MSG_READY ); MainForm.ShowStatus( STATUS_MSG_READY );
// Todo: Seen an AV next line when this method was invoked via an event handler.
FreeAndNil(ds); FreeAndNil(ds);
end; end;
end; end;
procedure TMDIChild.DiscardData(Sender: TVirtualStringTree; Node: PVirtualNode); procedure TMDIChild.DiscardNodeData(Sender: TVirtualStringTree; Node: PVirtualNode);
var var
Data: PGridResult; Data: PGridResult;
begin begin
@ -5585,9 +5628,9 @@ begin
Exit; Exit;
if Sender = DataGrid then gr := @FDataGridResult if Sender = DataGrid then gr := @FDataGridResult
else gr := @FQueryGridResult; else gr := @FQueryGridResult;
if Node.Index >= Cardinal(Length(gr.Rows)) then if Node.Index >= Cardinal(Length(gr.Rows)) then Exit;
Exit; EnsureChunkLoaded(Sender, Node);
EnsureDataLoaded(Sender, Node); if Node.Index >= Cardinal(Length(gr.Rows)) then Exit;
c := @gr.Rows[Node.Index].Cells[Column]; c := @gr.Rows[Node.Index].Cells[Column];
EditingCell := Sender.IsEditing and (Node = Sender.FocusedNode) and (Column = Sender.FocusedColumn); EditingCell := Sender.IsEditing and (Node = Sender.FocusedNode) and (Column = Sender.FocusedColumn);
if c.Modified then begin if c.Modified then begin
@ -5675,8 +5718,8 @@ procedure TMDIChild.DataGridAfterCellPaint(Sender: TBaseVirtualTree;
CellRect: TRect); CellRect: TRect);
begin begin
// Don't waist time // Don't waist time
if Column = -1 then if Column = -1 then Exit;
Exit; if Node.Index >= Cardinal(Length(FDataGridResult.Rows)) then Exit;
// Paint a red triangle at the top left corner of the cell // Paint a red triangle at the top left corner of the cell
if FDataGridResult.Rows[Node.Index].Cells[Column].Modified then if FDataGridResult.Rows[Node.Index].Cells[Column].Modified then
Mainform.PngImageListMain.Draw(TargetCanvas, CellRect.Left, CellRect.Top, 111); Mainform.PngImageListMain.Draw(TargetCanvas, CellRect.Left, CellRect.Top, 111);
@ -5813,7 +5856,6 @@ var
i: Integer; i: Integer;
sql, Val: WideString; sql, Val: WideString;
Row: PGridRow; Row: PGridRow;
ds: TDataSet;
begin begin
sql := 'UPDATE '+mask(SelectedTable)+' SET'; sql := 'UPDATE '+mask(SelectedTable)+' SET';
Row := @FDataGridResult.Rows[Sender.FocusedNode.Index]; Row := @FDataGridResult.Rows[Sender.FocusedNode.Index];
@ -5849,28 +5891,8 @@ begin
Row.Cells[i].IsNull := Row.Cells[i].NewIsNull; Row.Cells[i].IsNull := Row.Cells[i].NewIsNull;
end; end;
GridFinalizeEditing(Sender); GridFinalizeEditing(Sender);
sql := 'SELECT '; Row.Loaded := false;
for i := 0 to Length(FDataGridResult.Columns) - 1 do EnsureNodeLoaded(Sender, Sender.FocusedNode, GetWhereClause(Row, @FDataGridResult.Columns, FSelectedTableKeys));
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;
end; end;
end; end;
@ -6019,14 +6041,12 @@ begin
Vals := Copy(Vals, 1, Length(Vals)-2); Vals := Copy(Vals, 1, Length(Vals)-2);
Cols := Copy(Cols, 1, Length(Cols)-2); Cols := Copy(Cols, 1, Length(Cols)-2);
sql := 'INSERT INTO '+mask(SelectedTable)+' ('+Cols+') VALUES ('+Vals+')'; sql := 'INSERT INTO '+mask(SelectedTable)+' ('+Cols+') VALUES ('+Vals+')';
try
// Send INSERT query // Send INSERT query
ExecUpdateQuery(sql, False, True); ExecUpdateQuery(sql, False, True);
Result := True; Result := True;
Row.Loaded := false;
EnsureNodeLoaded(Sender, Node, GetWhereClause(Row, @FDataGridResult.Columns, FSelectedTableKeys));
GridFinalizeEditing(Sender); GridFinalizeEditing(Sender);
except
Result := False;
end;
end; end;
end; end;

View File

@ -837,7 +837,7 @@ begin
if not (coVisible in Grid.Header.Columns[i].Options) then if not (coVisible in Grid.Header.Columns[i].Options) then
Continue; Continue;
// Ensure basic data is loaded and load remainder of large fields. // 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); Mainform.Childwin.EnsureFullWidth(Grid, i, Node);
Data := Grid.Text[Node, i]; Data := Grid.Text[Node, i];
// Handle nulls. // Handle nulls.
@ -849,7 +849,7 @@ begin
tmp := tmp + ' </tr>' + CRLF; tmp := tmp + ' </tr>' + CRLF;
StreamWrite(S, tmp); StreamWrite(S, tmp);
// Release some memory. // Release some memory.
Mainform.Childwin.DiscardData(Grid, Node); Mainform.Childwin.DiscardNodeData(Grid, Node);
Node := Grid.GetNext(Node); Node := Grid.GetNext(Node);
end; end;
// footer: // footer:
@ -915,7 +915,7 @@ begin
if not (coVisible in Grid.Header.Columns[i].Options) then if not (coVisible in Grid.Header.Columns[i].Options) then
Continue; Continue;
// Ensure basic data is loaded and load remainder of large fields. // 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); Mainform.Childwin.EnsureFullWidth(Grid, i, Node);
Data := Grid.Text[Node, i]; Data := Grid.Text[Node, i];
// Remove 0x. // Remove 0x.
@ -934,7 +934,7 @@ begin
tmp := tmp + Terminator; tmp := tmp + Terminator;
StreamWrite(S, tmp); StreamWrite(S, tmp);
// Release some memory. // Release some memory.
Mainform.Childwin.DiscardData(Grid, Node); Mainform.Childwin.DiscardNodeData(Grid, Node);
Node := Grid.GetNext(Node); Node := Grid.GetNext(Node);
end; end;
Grid.Visible := true; Grid.Visible := true;
@ -973,7 +973,7 @@ begin
// Print cell start tag. // Print cell start tag.
tmp := tmp + #9#9'<' + Grid.Header.Columns[i].Text; tmp := tmp + #9#9'<' + Grid.Header.Columns[i].Text;
// Ensure basic data is loaded. // 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 if GridData.Rows[Node.Index].Cells[i].IsNull then tmp := tmp + ' isnull="true" />' + CRLF
else begin else begin
if GridData.Columns[i].IsBinary then tmp := tmp + ' format="hex"'; if GridData.Columns[i].IsBinary then tmp := tmp + ' format="hex"';
@ -994,7 +994,7 @@ begin
tmp := tmp + #9'</row>' + CRLF; tmp := tmp + #9'</row>' + CRLF;
StreamWrite(S, tmp); StreamWrite(S, tmp);
// Release some memory. // Release some memory.
Mainform.Childwin.DiscardData(Grid, Node); Mainform.Childwin.DiscardNodeData(Grid, Node);
Node := Grid.GetNext(Node); Node := Grid.GetNext(Node);
end; end;
// footer: // footer: