line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package DBIx::Tree::Persist; |
2
|
|
|
|
|
|
|
|
3
|
1
|
|
|
1
|
|
140404
|
use strict; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
41
|
|
4
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
32
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
1182
|
use Data::Dumper::Concise; # For Dumper(). |
|
1
|
|
|
|
|
11326
|
|
|
1
|
|
|
|
|
90
|
|
7
|
|
|
|
|
|
|
|
8
|
1
|
|
|
1
|
|
8
|
use DBI; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
36
|
|
9
|
|
|
|
|
|
|
|
10
|
1
|
|
|
1
|
|
821
|
use DBIx::Tree::Persist::Config; |
|
1
|
|
|
|
|
4
|
|
|
1
|
|
|
|
|
31
|
|
11
|
|
|
|
|
|
|
|
12
|
1
|
|
|
1
|
|
7
|
use Hash::FieldHash ':all'; |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
170
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
fieldhash my %copy_name => 'copy_name'; |
15
|
|
|
|
|
|
|
fieldhash my %data_structure => 'data_structure'; |
16
|
|
|
|
|
|
|
fieldhash my %dbh => 'dbh'; |
17
|
|
|
|
|
|
|
fieldhash my %starting_id => 'starting_id'; |
18
|
|
|
|
|
|
|
fieldhash my %table_name => 'table_name'; |
19
|
|
|
|
|
|
|
fieldhash my %verbose => 'verbose'; |
20
|
|
|
|
|
|
|
|
21
|
1
|
|
|
1
|
|
1741
|
use Tree; |
|
1
|
|
|
|
|
6600
|
|
|
1
|
|
|
|
|
35
|
|
22
|
1
|
|
|
1
|
|
1540
|
use Tree::Persist; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
our $VERSION = '1.04'; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
# ----------------------------------------------- |
27
|
|
|
|
|
|
|
|
28
|
|
|
|
|
|
|
sub build_structure |
29
|
|
|
|
|
|
|
{ |
30
|
|
|
|
|
|
|
my($self, @node) = @_; |
31
|
|
|
|
|
|
|
my($item_data) = []; |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
my(@children); |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
for my $node (@node) |
36
|
|
|
|
|
|
|
{ |
37
|
|
|
|
|
|
|
@children = $node -> children; |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
if ($#children >= 0) |
40
|
|
|
|
|
|
|
{ |
41
|
|
|
|
|
|
|
push @$item_data, |
42
|
|
|
|
|
|
|
{ |
43
|
|
|
|
|
|
|
text => $node -> value, |
44
|
|
|
|
|
|
|
submenu => |
45
|
|
|
|
|
|
|
{ |
46
|
|
|
|
|
|
|
id => 'id_' . $self -> get_id_of_node($node), |
47
|
|
|
|
|
|
|
itemdata => $self -> build_structure(@children), |
48
|
|
|
|
|
|
|
}, |
49
|
|
|
|
|
|
|
}; |
50
|
|
|
|
|
|
|
} |
51
|
|
|
|
|
|
|
else |
52
|
|
|
|
|
|
|
{ |
53
|
|
|
|
|
|
|
push @$item_data, {text => $node -> value}; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
} |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
return $item_data; |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
} # End of build_structure. |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
# ----------------------------------------------- |
62
|
|
|
|
|
|
|
# Note: We use 0, not null, as the parent of the root. |
63
|
|
|
|
|
|
|
# See comments to sub Create.create_one_table() for more detail. |
64
|
|
|
|
|
|
|
# Note: This code helps me understand how to build a tree a node at a time. |
65
|
|
|
|
|
|
|
|
66
|
|
|
|
|
|
|
sub copy_table |
67
|
|
|
|
|
|
|
{ |
68
|
|
|
|
|
|
|
my($self) = @_; |
69
|
|
|
|
|
|
|
my($old_table_name) = $self -> table_name; |
70
|
|
|
|
|
|
|
my($table_name) = $self -> copy_name; |
71
|
|
|
|
|
|
|
my($record) = $self -> dbh -> selectall_arrayref("select * from $old_table_name order by id", {Slice => {} }); |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
my($id); |
74
|
|
|
|
|
|
|
my($node); |
75
|
|
|
|
|
|
|
my($parent_id); |
76
|
|
|
|
|
|
|
my($row, $root_id); |
77
|
|
|
|
|
|
|
my(%seen); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
for $row (@$record) |
80
|
|
|
|
|
|
|
{ |
81
|
|
|
|
|
|
|
$id = $$row{id}; |
82
|
|
|
|
|
|
|
$parent_id = $$row{parent_id}; |
83
|
|
|
|
|
|
|
$node = Tree -> new($$row{value}); |
84
|
|
|
|
|
|
|
$seen{$id} = $node; |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
if ($seen{$parent_id}) |
87
|
|
|
|
|
|
|
{ |
88
|
|
|
|
|
|
|
$seen{$parent_id} -> add_child($node); |
89
|
|
|
|
|
|
|
} |
90
|
|
|
|
|
|
|
elsif ($parent_id == 0) |
91
|
|
|
|
|
|
|
{ |
92
|
|
|
|
|
|
|
$root_id = $id; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# This writes null, not 0, to the database, as the parent of the root. |
97
|
|
|
|
|
|
|
|
98
|
|
|
|
|
|
|
my($writer) = Tree::Persist -> create_datastore |
99
|
|
|
|
|
|
|
({ |
100
|
|
|
|
|
|
|
class_col => 'class', |
101
|
|
|
|
|
|
|
dbh => $self -> dbh, |
102
|
|
|
|
|
|
|
table => $table_name, |
103
|
|
|
|
|
|
|
tree => $seen{$root_id}, |
104
|
|
|
|
|
|
|
type => 'DB', |
105
|
|
|
|
|
|
|
}); |
106
|
|
|
|
|
|
|
|
107
|
|
|
|
|
|
|
} # End of copy_table. |
108
|
|
|
|
|
|
|
|
109
|
|
|
|
|
|
|
# -------------------------------------------------- |
110
|
|
|
|
|
|
|
|
111
|
|
|
|
|
|
|
sub get_id_of_node |
112
|
|
|
|
|
|
|
{ |
113
|
|
|
|
|
|
|
my($self, $node) = @_; |
114
|
|
|
|
|
|
|
my($meta) = $node -> meta; |
115
|
|
|
|
|
|
|
my(@key) = grep{length} keys %$meta; |
116
|
|
|
|
|
|
|
my($id) = $$meta{$key[0]}{id}; |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
return $id; |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
} # End of get_id_of_node; |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
# ----------------------------------------------- |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
sub log |
125
|
|
|
|
|
|
|
{ |
126
|
|
|
|
|
|
|
my($self, $message) = @_; |
127
|
|
|
|
|
|
|
$message ||= ''; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
if ($self -> verbose) |
130
|
|
|
|
|
|
|
{ |
131
|
|
|
|
|
|
|
print "$message\n"; |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
} # End of log. |
135
|
|
|
|
|
|
|
|
136
|
|
|
|
|
|
|
# ----------------------------------------------- |
137
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
sub new |
139
|
|
|
|
|
|
|
{ |
140
|
|
|
|
|
|
|
my($class, %arg) = @_; |
141
|
|
|
|
|
|
|
$arg{copy_name} ||= ''; |
142
|
|
|
|
|
|
|
$arg{dbh} ||= ''; |
143
|
|
|
|
|
|
|
$arg{data_structure} ||= 0; |
144
|
|
|
|
|
|
|
$arg{starting_id} ||= 1; |
145
|
|
|
|
|
|
|
$arg{table_name} ||= ''; |
146
|
|
|
|
|
|
|
$arg{verbose} ||= 0; |
147
|
|
|
|
|
|
|
my($self) = from_hash(bless({}, $class), \%arg); |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
if (! $self -> dbh) |
150
|
|
|
|
|
|
|
{ |
151
|
|
|
|
|
|
|
my($config) = DBIx::Tree::Persist::Config -> new -> config; |
152
|
|
|
|
|
|
|
my(@dsn) = ($$config{dsn}, $$config{username}, $$config{password}); |
153
|
|
|
|
|
|
|
my($attr) = {}; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
$self -> dbh(DBI -> connect(@dsn, $attr) ); |
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
|
158
|
|
|
|
|
|
|
return $self; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
} # End of new. |
161
|
|
|
|
|
|
|
|
162
|
|
|
|
|
|
|
# ----------------------------------------------- |
163
|
|
|
|
|
|
|
|
164
|
|
|
|
|
|
|
sub pretty_print |
165
|
|
|
|
|
|
|
{ |
166
|
|
|
|
|
|
|
my($self, $tree) = @_; |
167
|
|
|
|
|
|
|
|
168
|
|
|
|
|
|
|
my($depth); |
169
|
|
|
|
|
|
|
my($id); |
170
|
|
|
|
|
|
|
my($value); |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
for my $node ($tree -> traverse($tree -> PRE_ORDER) ) |
173
|
|
|
|
|
|
|
{ |
174
|
|
|
|
|
|
|
$depth = $node -> depth; |
175
|
|
|
|
|
|
|
$id = $self -> get_id_of_node($node); |
176
|
|
|
|
|
|
|
$value = $node -> value; |
177
|
|
|
|
|
|
|
|
178
|
|
|
|
|
|
|
$self -> log(' ' x $depth . "$value ($id)"); |
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
|
|
|
|
|
|
} # End of pretty_print. |
182
|
|
|
|
|
|
|
|
183
|
|
|
|
|
|
|
# ----------------------------------------------- |
184
|
|
|
|
|
|
|
|
185
|
|
|
|
|
|
|
sub run |
186
|
|
|
|
|
|
|
{ |
187
|
|
|
|
|
|
|
my($self) = @_; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
$self -> copy_name ? $self -> copy_table : $self -> traverse; |
190
|
|
|
|
|
|
|
|
191
|
|
|
|
|
|
|
return 0; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
} # End of run. |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
# ----------------------------------------------- |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub traverse |
198
|
|
|
|
|
|
|
{ |
199
|
|
|
|
|
|
|
my($self) = @_; |
200
|
|
|
|
|
|
|
|
201
|
|
|
|
|
|
|
$self -> log('Traversing table ' . $self -> table_name . ' with a starting_id of ' . $self -> starting_id); |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
# Read tree from database. |
204
|
|
|
|
|
|
|
|
205
|
|
|
|
|
|
|
my($reader) = Tree::Persist -> connect |
206
|
|
|
|
|
|
|
({ |
207
|
|
|
|
|
|
|
class_col => 'class', |
208
|
|
|
|
|
|
|
dbh => $self -> dbh, |
209
|
|
|
|
|
|
|
id => $self -> starting_id, |
210
|
|
|
|
|
|
|
table => $self -> table_name, |
211
|
|
|
|
|
|
|
type => 'DB', |
212
|
|
|
|
|
|
|
}); |
213
|
|
|
|
|
|
|
my($tree) = $reader -> tree; |
214
|
|
|
|
|
|
|
|
215
|
|
|
|
|
|
|
# Traverse tree. |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
$self -> data_structure ? $self -> ugly_print($tree) : $self -> pretty_print($tree); |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
} # End of traverse. |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
# ----------------------------------------------- |
222
|
|
|
|
|
|
|
|
223
|
|
|
|
|
|
|
sub ugly_print |
224
|
|
|
|
|
|
|
{ |
225
|
|
|
|
|
|
|
my($self, $tree) = @_; |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
$self -> log(Dumper($self -> build_structure($tree) ) ); |
228
|
|
|
|
|
|
|
|
229
|
|
|
|
|
|
|
} # End of ugly_print. |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
# ----------------------------------------------- |
232
|
|
|
|
|
|
|
|
233
|
|
|
|
|
|
|
1; |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
=pod |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
=head1 NAME |
238
|
|
|
|
|
|
|
|
239
|
|
|
|
|
|
|
DBIx::Tree::Persist - Play with Tree and Tree::Persist a la DBIx::Tree |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
=head1 Synopsis |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
First, edit lib/DBIx/Tree/Persist/.htdbix.tree.persist.conf. |
244
|
|
|
|
|
|
|
|
245
|
|
|
|
|
|
|
Then run the scripts in this order (see scripts/test.sh): |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
=over 4 |
248
|
|
|
|
|
|
|
|
249
|
|
|
|
|
|
|
=item scripts/drop.tables.pl |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
Drop tables one and two. |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
Of course, you only run this after running create.tables.pl. |
254
|
|
|
|
|
|
|
|
255
|
|
|
|
|
|
|
=item scripts/create.tables.pl |
256
|
|
|
|
|
|
|
|
257
|
|
|
|
|
|
|
Create tables one and two. |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
Some notes regarding the ways tables one and two are declared (in C): |
260
|
|
|
|
|
|
|
|
261
|
|
|
|
|
|
|
=over 4 |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
=item Null 'v' Not Null |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
parent_id is not 'not null', because L stores a null as the parent of the root. |
266
|
|
|
|
|
|
|
|
267
|
|
|
|
|
|
|
=item Foreign Keys |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
If parent_id is 'references two(id)', then it cannot be set to 0 for the root, because id 0 does not exist. |
270
|
|
|
|
|
|
|
|
271
|
|
|
|
|
|
|
However, by omitting 'references two(id)', the parent_id of the root can be (manually) set to 0, and |
272
|
|
|
|
|
|
|
L still reads in the tree properly. |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
=back |
275
|
|
|
|
|
|
|
|
276
|
|
|
|
|
|
|
=item scripts/populate.tables.pl |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
Populate table two from the text file data/two.txt. |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
The data comes from the docs for L. |
281
|
|
|
|
|
|
|
|
282
|
|
|
|
|
|
|
populate.tables.pl uses neither L nor L. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
The code in C uses 0 as the parent_id of the root, whereas L uses null. |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
This is both to demonstrate the point made above that L handles this, and to adhere to my convention |
287
|
|
|
|
|
|
|
to use 'not null' whenever possible. Clearly, this is not possible when it's L writing to the |
288
|
|
|
|
|
|
|
database. Hence table two which I write can use 'not null', but table one can't use it, since table one is |
289
|
|
|
|
|
|
|
populated by L. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
This convention is adopted from: |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
Joe Celko's SQL for Smarties 2nd edition |
294
|
|
|
|
|
|
|
Morgan Kaufmann |
295
|
|
|
|
|
|
|
1-55860-576-2 |
296
|
|
|
|
|
|
|
Section 6.9, page 120, Design Advice for NULLs |
297
|
|
|
|
|
|
|
|
298
|
|
|
|
|
|
|
=item scripts/report.tables.pl |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
Report the record counts from tables one and two. |
301
|
|
|
|
|
|
|
|
302
|
|
|
|
|
|
|
=item scripts/tree.pl -t two -v |
303
|
|
|
|
|
|
|
|
304
|
|
|
|
|
|
|
Traverse and print table two. |
305
|
|
|
|
|
|
|
|
306
|
|
|
|
|
|
|
This run uses L, and L. |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
=item scripts/tree.pl -t two -c one |
309
|
|
|
|
|
|
|
|
310
|
|
|
|
|
|
|
Copy table two to table one. |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
This run uses L, and L. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
=item scripts/tree.pl -t two -c one |
315
|
|
|
|
|
|
|
|
316
|
|
|
|
|
|
|
Copy table two to table one, again. Table one now contains 2 independent trees. |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=item scripts/tree.pl -t one -s 1 -v |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Traverse and print table one, starting from id = 1. |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=item scripts/tree.pl -t one -s 21 -v |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
Traverse and print table one, starting from id = 21. |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
The tree structures for the 2 trees printed by the last 2 commands will be the same. |
327
|
|
|
|
|
|
|
However, since the trees are stored at different offsets within table one, the ids |
328
|
|
|
|
|
|
|
associated with each corresponding node will be different. |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=item scripts/tree.pl -t one -d -s 1 -v |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
Use the -data_structure option to call the C method, and to output |
333
|
|
|
|
|
|
|
that structure instead of pretty-printing the tree. |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
=back |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
=head1 Description |
338
|
|
|
|
|
|
|
|
339
|
|
|
|
|
|
|
L provides sample code for playing with Tree and Tree::Persist a la DBIx::Tree. |
340
|
|
|
|
|
|
|
|
341
|
|
|
|
|
|
|
=head1 Distributions |
342
|
|
|
|
|
|
|
|
343
|
|
|
|
|
|
|
This module is available as a Unix-style distro (*.tgz). |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
See L for |
346
|
|
|
|
|
|
|
help on unpacking and installing distros. |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
=head1 Method: build_structure($root) |
349
|
|
|
|
|
|
|
|
350
|
|
|
|
|
|
|
Returns a Perl data structure which can be turned into JSON. |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
The -data_structure option to scripts/tree.pl gives you access to this feature. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=head1 Method: copy_table() |
355
|
|
|
|
|
|
|
|
356
|
|
|
|
|
|
|
If copy_name is used to pass a table name to new(), sub run() calls sub copy_table(). |
357
|
|
|
|
|
|
|
|
358
|
|
|
|
|
|
|
If copy_name is not used, sub run() calls sub traverse(). |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
sub copy_table() shows how to build a tree based on a linear scan of a dataset. |
361
|
|
|
|
|
|
|
|
362
|
|
|
|
|
|
|
=head1 Method: new() |
363
|
|
|
|
|
|
|
|
364
|
|
|
|
|
|
|
See scripts/tree.pl for how to pass sample parameters to new() via a command-line program. |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
C takes a hash of parameters: |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
=over 4 |
369
|
|
|
|
|
|
|
|
370
|
|
|
|
|
|
|
=item copy_name => 'A table name' |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
copy_name is optional. |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
If specified, the code copies the data from the table named with the -t option |
375
|
|
|
|
|
|
|
to the table named with the -c option. |
376
|
|
|
|
|
|
|
|
377
|
|
|
|
|
|
|
=item dbh => $dbh |
378
|
|
|
|
|
|
|
|
379
|
|
|
|
|
|
|
dbh is optional. |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
If specified, the code uses the $dbh provided. |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
If not specified, the code reads the config file lib/DBIx/Tree/Persist/.htdbix.tree.persist.conf |
384
|
|
|
|
|
|
|
to get parameters and calls DBI -> connect() to generate a dbh. |
385
|
|
|
|
|
|
|
|
386
|
|
|
|
|
|
|
This is mainly used for testing. See t/test.t. |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
=item starting_id => N |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
starting_id is optional. |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
If specified, a tree is read from the table named with the -t option, starting at the |
393
|
|
|
|
|
|
|
id given here. |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
If not specified, starting_id defaults to 1. |
396
|
|
|
|
|
|
|
|
397
|
|
|
|
|
|
|
=item table_name => 'A table name' |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
table_name is mandatory. |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
The table named with the -t option is always used as input. |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
It will (probably) have been populated with scripts/populate.tables.pl. |
404
|
|
|
|
|
|
|
|
405
|
|
|
|
|
|
|
=item verbose => N |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
verbose is optional. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
If specified and > 0, if provides more progress reports. |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
If not specified, it defaults to 0, which minimizes output. |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
=back |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
=head1 Method: pretty_print($root) |
416
|
|
|
|
|
|
|
|
417
|
|
|
|
|
|
|
Print the tree nicely. This method is called from C if the -data_structure option |
418
|
|
|
|
|
|
|
is not used. |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
=head1 Method: run() |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
After calling new(...), you have to call run(). See scripts/tree.pl for sample code. |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
=head1 Method: traverse() |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
If copy_name is used to pass a table name to new(), sub run() calls sub copy_table(). |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
If copy_name is not used, sub run() calls sub traverse(). |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
sub traverse() shows how to build a tree from a disk file, and to then process that tree. |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
if the -data_structure option (to scripts/tree.pl) is used, the tree is converted to a data structure, |
433
|
|
|
|
|
|
|
which is then printed using the C method of L. |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
If the -data_structure option is not used, the tree is pretty-printed by calling the method C. |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=head1 Support |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
Email the author, or log a bug on RT: |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
L. |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
=head1 See Also |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
L. This module has its own list of See Also references. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
L. This module has its own list of See Also references. |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
L. |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
L. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
L. |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
L. |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
L. |
458
|
|
|
|
|
|
|
|
459
|
|
|
|
|
|
|
=head1 Author |
460
|
|
|
|
|
|
|
|
461
|
|
|
|
|
|
|
L was written by Ron Savage Iron@savage.net.auE> in 2010. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
Home page: L. |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
=head1 Copyright |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
Australian copyright (c) 2010, Ron Savage. |
468
|
|
|
|
|
|
|
|
469
|
|
|
|
|
|
|
All Programs of mine are 'OSI Certified Open Source Software'; |
470
|
|
|
|
|
|
|
you can redistribute them and/or modify them under the terms of |
471
|
|
|
|
|
|
|
The Artistic License, a copy of which is available at: |
472
|
|
|
|
|
|
|
L. |
473
|
|
|
|
|
|
|
|
474
|
|
|
|
|
|
|
=cut |