X-Git-Url: http://wagnertech.de/git?a=blobdiff_plain;f=scripts%2Fdbupgrade2_tool.pl;h=bef04f0dd6753433e27852808fd941feda32c538;hb=c7edb24800396748f2bf1e40ff05f90a18d31b02;hp=ce1ab29c2e7fcf3f5a35b33f309474a418f7e58a;hpb=fdec9e469cd6ad9025a7bdb4bafa6ec61220191b;p=kivitendo-erp.git diff --git a/scripts/dbupgrade2_tool.pl b/scripts/dbupgrade2_tool.pl index ce1ab29c2..bef04f0dd 100755 --- a/scripts/dbupgrade2_tool.pl +++ b/scripts/dbupgrade2_tool.pl @@ -15,6 +15,7 @@ use English '-no_match_vars'; use DBI; use Data::Dumper; use Getopt::Long; +use Text::Iconv; use SL::LXDebug; @@ -32,20 +33,21 @@ use SL::DBUtils; ####### my ($opt_list, $opt_tree, $opt_rtree, $opt_nodeps, $opt_graphviz, $opt_help); -my ($opt_user, $opt_apply); +my ($opt_user, $opt_apply, $opt_applied, $opt_format, $opt_test_utf8); +my ($opt_dbhost, $opt_dbport, $opt_dbname, $opt_dbuser, $opt_dbpassword); our (%myconfig, $form, $user, $auth); sub show_help { - my $help_text = <<'END_HELP' + my $help_text = <<"END_HELP" dbupgrade2_tool.pl [options] A validation and information tool for the database upgrade scripts - in 'sql/Pg-upgrade2'. + in \'sql/Pg-upgrade2\'. At startup dbupgrade2_tool.pl will always check the consistency of all database upgrade scripts (e.g. circular references, invalid - formats, missing meta information). You can but don't have to specifiy + formats, missing meta information). You can but don\'t have to specifiy additional actions. Actions: @@ -55,21 +57,34 @@ dbupgrade2_tool.pl [options] --graphviz[=file] Create a Postscript document showing a tree of all database upgrades and their dependencies. If no file name is given then the output is - written to 'db_dependencies.ps'. + written to \'db_dependencies.png\'. + --format=... Format for the graphviz output. Defaults to + \'png\'. All values that the command \'dot\' accepts + for it\'s option \'-T\' are acceptable. --nodeps List all database upgrades that no other upgrade depends on - --apply=tag Applies the database upgrades 'tag' and all - upgrades it depends on. If '--apply' is used - then the option '--user' must be used as well. + --apply=tag Applies the database upgrades \'tag\' and all + upgrades it depends on. If \'--apply\' is used + then the option \'--user\' must be used as well. + --applied List the applied database upgrades for the + database that the user given with \'--user\' uses. + --test-utf8 Tests a PostgreSQL cluster for proper UTF-8 support. + You have to specify the database to test with the + parameters --dbname, --dbhost, --dbport, --dbuser + and --dbpassword. --help Show this help and exit. Options: --user=name The name of the user configuration to use for database connectivity. -END_HELP - ; + --dbname=name Database connection options for the UTF-8 + --dbhost=host handling test. + --dbport=port + --dbuser=user + --dbpassword=pw - # Syntax-Highlighting-Fix für Emacs: ' +END_HELP +; print $help_text; @@ -152,14 +167,17 @@ sub dump_tree_reverse { } sub dump_graphviz { - my $file_name = shift || "db_dependencies.ps"; + my %params = @_; - print "GRAPHVIZ POSTCRIPT\n\n"; + my $format = $params{format} || "png"; + my $file_name = $params{file_name} || "db_dependencies.${format}"; + + print "GRAPHVIZ OUTPUT -- format: ${format}\n\n"; print "Output will be written to '${file_name}'\n"; calc_rev_depends(); - $dot = "|dot -Tps "; + $dot = "|dot -T${format} "; open OUT, "${dot}> \"${file_name}\"" || die; print OUT @@ -258,6 +276,60 @@ sub apply_upgrade { $dbh->disconnect(); } +sub dump_sql_result { + my ($results, $column_order) = @_; + + my %column_lengths = map { $_, length $_ } keys %{ $results->[0] }; + + foreach my $row (@{ $results }) { + map { $column_lengths{$_} = length $row->{$_} if (length $row->{$_} > $column_lengths{$_}) } keys %{ $row }; + } + + my @sorted_names; + if ($column_order && scalar @{ $column_order }) { + @sorted_names = @{ $column_order }; + } else { + @sorted_names = sort keys %column_lengths; + } + + my $format = join('|', map { '%-' . $column_lengths{$_} . 's' } @sorted_names) . "\n"; + + printf $format, @sorted_names; + print join('+', map { '-' x $column_lengths{$_} } @sorted_names) . "\n"; + + foreach my $row (@{ $results }) { + printf $format, map { $row->{$_} } @sorted_names; + } + printf "(\%d row\%s)\n", scalar @{ $results }, scalar @{ $results } > 1 ? 's' : ''; +} + +sub dump_applied { + my @results; + + my $dbh = $form->dbconnect_noauto(\%myconfig); + + $dbh->{PrintWarn} = 0; + $dbh->{PrintError} = 0; + + $user->create_schema_info_table($form, $dbh); + + my $query = qq|SELECT tag, login, itime FROM schema_info ORDER BY itime|; + $sth = $dbh->prepare($query); + $sth->execute() || $form->dberror($query); + while (my $ref = $sth->fetchrow_hashref()) { + push @results, $ref; + } + $sth->finish(); + + $dbh->disconnect(); + + if (!scalar @results) { + print "No database upgrades have been applied yet.\n"; + } else { + dump_sql_result(\@results, [qw(tag login itime)]); + } +} + sub build_upgrade_order { my $name = shift; my $order = shift; @@ -283,31 +355,40 @@ eval { require "config/lx-erp.conf"; }; eval { require "config/lx-erp-local.conf"; } if (-f "config/lx-erp-local.conf"); $form = Form->new(); -$locale = Locale->new("de", "login"); +$locale = Locale->new("de"); ####### ####### ####### -GetOptions("list" => \$opt_list, - "tree" => \$opt_tree, - "rtree" => \$opt_rtree, - "nodeps" => \$opt_nodeps, - "graphviz:s" => \$opt_graphviz, - "user=s" => \$opt_user, - "apply=s" => \$opt_apply, - "help" => \$opt_help, +GetOptions("list" => \$opt_list, + "tree" => \$opt_tree, + "rtree" => \$opt_rtree, + "nodeps" => \$opt_nodeps, + "graphviz:s" => \$opt_graphviz, + "format:s" => \$opt_format, + "user=s" => \$opt_user, + "apply=s" => \$opt_apply, + "applied" => \$opt_applied, + "test-utf8" => \$opt_test_utf8, + "dbhost:s" => \$opt_dbhost, + "dbport:s" => \$opt_dbport, + "dbname:s" => \$opt_dbname, + "dbuser:s" => \$opt_dbuser, + "dbpassword:s" => \$opt_dbpassword, + "help" => \$opt_help, ); show_help() if ($opt_help); $controls = parse_dbupdate_controls($form, "Pg"); -dump_list() if ($opt_list); -dump_tree() if ($opt_tree); -dump_tree_reverse() if ($opt_rtree); -dump_graphviz($opt_graphviz) if (defined $opt_graphviz); -dump_nodeps() if ($opt_nodeps); +dump_list() if ($opt_list); +dump_tree() if ($opt_tree); +dump_tree_reverse() if ($opt_rtree); +dump_graphviz('file_name' => $opt_graphviz, + 'format' => $opt_format) if (defined $opt_graphviz); +dump_nodeps() if ($opt_nodeps); if ($opt_user) { $auth = SL::Auth->new(); @@ -330,6 +411,43 @@ if ($opt_user) { } if ($opt_apply) { - $form->error("--apply used but no configuration file given with --user.") if (!$user); + $form->error("--apply used but no user name given with --user.") if (!$user); apply_upgrade($opt_apply); } + +if ($opt_applied) { + $form->error("--applied used but no user name given with --user.") if (!$user); + dump_applied(); +} + +if ($opt_test_utf8) { + $form->error("--test-utf8 used but no database name given with --dbname.") if (!$opt_dbname); + + my $iconv_to_utf8 = Text::Iconv->new("ISO-8859-15", "UTF-8"); + my $iconv_from_utf8 = Text::Iconv->new("UTF-8", "ISO-8859-15"); + + my $umlaut_upper = 'Ä'; + my $umlaut_upper_utf8 = $iconv_to_utf8->convert($umlaut_upper); + + my $dbconnect = "dbi:Pg:dbname=${opt_dbname}"; + $dbconnect .= ";host=${opt_dbhost}" if ($opt_dbhost); + $dbconnect .= ";port=${opt_dbport}" if ($opt_dbport); + + my $dbh = DBI->connect($dbconnect, $opt_dbuser, $opt_dbpassword); + + $form->error("UTF-8 test: Database connect failed (" . $DBI::errstr . ")") if (!$dbh); + + my ($umlaut_lower_utf8) = $dbh->selectrow_array(qq|SELECT lower(?)|, undef, $umlaut_upper_utf8); + + $dbh->disconnect(); + + my $umlaut_lower = $iconv_from_utf8->convert($umlaut_lower_utf8); + + if ($umlaut_lower eq 'ä') { + print "UTF-8 test was successful.\n"; + } elsif ($umlaut_lower eq 'Ä') { + print "UTF-8 test was NOT successful: Umlauts are not modified (this might be partially ok, but you should probably not use UTF-8 on this cluster).\n"; + } else { + print "UTF-8 test was NOT successful: Umlauts are destroyed. Do not use UTF-8 on this cluster.\n"; + } +}