1 package SL::DBUpgrade2;
6 @EXPORT = qw(parse_dbupdate_controls sort_dbupdate_controls);
8 sub parse_dbupdate_controls {
9 $main::lxdebug->enter_sub();
11 my ($form, $dbdriver) = @_;
13 my $locale = $main::locale;
18 my $path = "sql/${dbdriver}-upgrade2";
20 foreach my $file_name (<$path/*.sql>, <$path/*.pl>) {
21 next unless (open(IN, $file_name));
23 my $file = $file_name;
33 next unless (/^(--|\#)\s*\@/);
38 my @fields = split(/\s*:\s*/, $_, 2);
39 next unless (scalar(@fields) == 2);
41 if ($fields[0] eq "depends") {
42 push(@{$control->{"depends"}}, split(/\s+/, $fields[1]));
44 $control->{$fields[0]} = $fields[1];
48 _control_error($form, $file_name,
49 $locale->text("Missing 'tag' field."))
50 unless ($control->{"tag"});
52 _control_error($form, $file_name,
53 $locale->text("The 'tag' field must only consist of " .
54 "alphanumeric characters or the carachters " .
56 if ($control->{"tag"} =~ /[^a-zA-Z0-9_\(\)\-]/);
58 _control_error($form, $file_name,
59 sprintf($locale->text("More than one control file " .
60 "with the tag '%s' exist."),
62 if (defined($all_controls{$control->{"tag"}}));
64 _control_error($form, $file_name,
65 sprintf($locale->text("Missing 'description' field.")))
66 unless ($control->{"description"});
68 $control->{"priority"} *= 1;
69 $control->{"priority"} = 1000 unless ($control->{"priority"});
71 $control->{"file"} = $file;
73 map({ delete($control->{$_}); } qw(depth applied));
75 $all_controls{$control->{"tag"}} = $control;
80 foreach my $control (values(%all_controls)) {
81 foreach my $dependency (@{$control->{"depends"}}) {
82 _control_error($form, $control->{"file"},
83 sprintf($locale->text("Unknown dependency '%s'."),
85 if (!defined($all_controls{$dependency}));
88 map({ $_->{"loop"} = 0; } values(%all_controls));
89 _check_for_loops($form, $control->{"file"}, \%all_controls,
93 map({ _dbupdate2_calculate_depth(\%all_controls, $_->{"tag"}) }
94 values(%all_controls));
96 $main::lxdebug->leave_sub();
98 return \%all_controls;
101 sub _check_for_loops {
102 my ($form, $file_name, $controls, $tag, @path) = @_;
106 my $ctrl = $controls->{$tag};
108 if ($ctrl->{"loop"} == 1) {
110 _control_error($form, $file_name,
111 $main::locale->text("Dependency loop detected:") .
112 " " . join(" -> ", @path))
113 } elsif ($ctrl->{"loop"} == 0) {
116 map({ _check_for_loops($form, $file_name, $controls, $_, @path); }
117 @{ $ctrl->{"depends"} });
123 my ($form, $file_name, $message) = @_;
126 my $locale = $main::locale;
128 $form->error(sprintf($locale->text("Error in database control file '%s': %s"),
129 $file_name, $message));
132 sub _dbupdate2_calculate_depth {
133 $main::lxdebug->enter_sub();
135 my ($tree, $tag) = @_;
137 my $node = $tree->{$tag};
139 return $main::lxdebug->leave_sub() if (defined($node->{"depth"}));
143 foreach $tag (@{$node->{"depends"}}) {
144 _dbupdate2_calculate_depth($tree, $tag);
145 my $value = $tree->{$tag}->{"depth"};
146 $max_depth = $value if ($value > $max_depth);
149 $node->{"depth"} = $max_depth + 1;
151 $main::lxdebug->leave_sub();
154 sub sort_dbupdate_controls {
156 sort({ $a->{"depth"} != $b->{"depth"} ? $a->{"depth"} <=> $b->{"depth"} :
157 $a->{"priority"} != $b->{"priority"} ?
158 $a->{"priority"} <=> $b->{"priority"} :
159 $a->{"tag"} cmp $b->{"tag"} } values(%{$_[0]}));