Re: recursive treeview fill - problem



Anwendungsprogrammierer@xxxxxx wrote:
i got a table with this layout:

id__ name parent_id__

it stores data to recursively fill a treeview.
Now I wrote a function like that to fill the tree, but it does not seem
to work right, it adds one empty item below every node. I cant find the
flaw - pls help.
first call is filltree(nil,'')

I've begun by fixing the indentation. Sloppy code is buggy code.

procedure TMain.FillTree(N : TTreeNode; Parent : String);
var x, rsC : _recordset;
TreeParent, treechild : TTreeNode;
cmd : string;
begin
With self.navTree.Items do

Begin by removing the "with" statement. It can lead to nothing but problems.

begin
if n =nil then begin
// clear nodes
clear;
cmd:='SELECT id__,name, parent_id__ FROM tbl_Entries WHERE
parent_id__ is NULL';

If the parent_id__ field is always going to be null in the result, why select it?

x:=dblayer.Execute(cmd);
while not x.EOF do begin
application.ProcessMessages;
if x.Fields.Item[2].Value = null then begin

Doesn't the field object have an IsNull property you could check instead?

And aren't you guaranteed that the field will be null since that was the condition in the WHERE clause?

treeparent:=add(nil,x.Fields.Item[1].Value);
cmd:='SELECT id__,name, parent_id__ FROM tbl_Entries WHERE
parent_id__ =''' + x.Fields.Item[0].Value + '''';

You shouldn't need to select the parent_id__ field here, either. You already know exactly what it's value is going to be, so don't make the database send that value back to you for every record it finds.

rsc:=dblayer.Execute(cmd);

Are you sure your database system allows you to initiate a query while another one from the same thread is still open? Once you assign rsc, are you sure x is still valid?

while not rsc.EOF do begin
if rsc.Fields[2].Value ='' then
application.ProcessMessages

Will that condition ever be true? Field 2 is for parent_id__, right? You've selected that field and required it to be equal to the id__ field of the parent. Will the ID ever be an empty string?

else begin
showmessage(rsc.Fields.Item[0].value +
':'+rsc.Fields.Item[1].value);
TreeChild :=
AddChild(TreeParent,rsc.Fields.Item[1].value);
FillTree(TreeChild,rsc.Fields.item[0].value);
end;
if not rsc.EOF then rsc.MoveNext;

Get rid of the condition. You already know EOF is False, or you wouldn't be inside the loop in the first place. Just call MoveNext directly.

end;
end;
if not x.EOF then x.movenext;

Same here.

end;
end
else begin
if parent='' then exit;
cmd:='SELECT id__,name, parent_id__ FROM tbl_Entries WHERE
parent_id__ =''' + parent + '''';
rsc:=dblayer.Execute(cmd);
repeat

Your two loops above where both "while" loops. Now you're using a "repeat" loop, which is guaranteed to run at least once. I suspect this is why you end up with too many items in your tree.

TreeChild := AddChild(n,rsc.Fields.Item[1].value);
FillTree(TreeChild,rsc.Fields.Item[0].Value);

A recursive call that executes a query will have the same problems as a nested query above. Make sure your database tool allows that.

if not rsc.EOF then rsc.movenext;
until rsc.EOF
end;
end;
end;

I think the main "then" branch is doing too much. It should only have one loop, just like the "else" branch. As it is now, the "then" branch is responsible for filling two tiers of the tree instead of just one. That means you've duplicated code for populating the non-parent levels of the tree.

--
Rob
.



Relevant Pages

  • Re: JTree & database: ID column ?
    ... > from database and for it I use ID1 column which is unique ... > and every number in a code represents the place in a parent node. ... And if you can construct a tree ... reverse-index is NOT an auto-inserted id value, although it has to be unique ...
    (comp.lang.java.gui)
  • Re: Parsing and storing formulas
    ... you could easily store different views/stored ... >I was wondering how I can parse a mathematical formula in a storable way. ... > be stored for in the database. ... > The second idea is to represent the formula as a tree. ...
    (microsoft.public.dotnet.languages.csharp)
  • RE: Can I create a search engine?
    ... You can create an unbound field on a form then query. ... This will return any record with Tree in that field. ... I have a database which contains a library of topics and related notes associated with books, movies, internet, etc. ...
    (microsoft.public.access.forms)
  • Re: Managing Genealogy Relationships in FMP 8.5
    ... the database (the file has tables for managing photos, documents, ... family tree, he's variously a brother, husband, grandfather, son, ... but a complete map is hella more efficient. ... Replace a Sort field to 1. ...
    (comp.databases.filemaker)
  • Re: Unique identifier in every treenode?
    ... The important part about that code is the recursion, which will be a common element in any implementation that enumerates the tree completely.. ... Then when saving, you'd include for each node the Guid of the _parent_ of that node. ... But my understanding is that you can create a database where one of the columns is a unique identifier, and optionally where the unique identifier is automatically generated when you add a record to the database. ...
    (microsoft.public.dotnet.languages.csharp)