+
+sub dbh_do {
+ my ($dbh, $query, %params) = @_;
+
+ if (ref($query)) {
+ return if $query->execute(@{ $params{bind} || [] });
+ die($dbh->errstr);
+ }
+
+ return if $dbh->do($query, undef, @{ $params{bind} || [] });
+
+ die($params{message} . ": " . $dbh->errstr) if $params{message};
+ die("Query failed: " . $dbh->errstr . " ; query: $query");
+}
+
+parse_args(\%config);
+setup();
+check_errors_in_package_names();
+
+my %tables_by_domain = make_tables();
+
+foreach my $domain (keys %tables_by_domain) {
+ my @tables = @{ $tables_by_domain{$domain} };
+ my @unknown_tables = grep { !$package_names{$domain}->{$_} } @tables;
+ if (@unknown_tables) {
+ error("The following tables do not have entries in \%SL::DB::Helper::Mappings::${domain}_package_names: " . join(' ', sort @unknown_tables));
+ exit 1;
+ }
+
+ process_table($domain, $_, $package_names{$domain}->{$_}) for @tables;
+}
+
+1;
+
+__END__
+
+=encoding utf-8
+
+=head1 NAME
+
+rose_auto_create_model - mana Rose::DB::Object classes for kivitendo
+
+=head1 SYNOPSIS
+
+ scripts/rose_auto_create_model.pl OPTIONS TARGET
+
+ # use other client than devel.client
+ scripts/rose_auto_create_model.pl --test-client TARGET
+ scripts/rose_auto_create_model.pl --client name-or-id TARGET
+
+ # TARGETS:
+ # updates all models
+ scripts/rose_auto_create_model.pl --all [--db db]
+
+ # updates only customer table, login taken from config
+ scripts/rose_auto_create_model.pl customer
+
+ # updates only parts table, package will be Part
+ scripts/rose_auto_create_model.pl parts=Part
+
+ # try to update parts, but don't do it. tell what would happen in detail
+ scripts/rose_auto_create_model.pl --no-commit parts
+
+=head1 DESCRIPTION
+
+Rose::DB::Object comes with a nice function named auto initialization with code
+generation. The documentation of Rose describes it like this:
+
+I<[...] auto-initializing metadata at runtime by querying the database has many
+caveats. An alternate approach is to query the database for metadata just once,
+and then generate the equivalent Perl code which can be pasted directly into
+the class definition in place of the call to auto_initialize.>
+
+I<Like the auto-initialization process itself, perl code generation has a
+convenient wrapper method as well as separate methods for the individual parts.
+All of the perl code generation methods begin with "perl_", and they support
+some rudimentary code formatting options to help the code conform to you
+preferred style. Examples can be found with the documentation for each perl_*
+method.>
+
+I<This hybrid approach to metadata population strikes a good balance between
+upfront effort and ongoing maintenance. Auto-generating the Perl code for the
+initial class definition saves a lot of tedious typing. From that point on,
+manually correcting and maintaining the definition is a small price to pay for
+the decreased start-up cost, the ability to use the class in the absence of a
+database connection, and the piece of mind that comes from knowing that your
+class is stable, and won't change behind your back in response to an "action at
+a distance" (i.e., a database schema update).>
+
+Unfortunately this reads easier than it is, since classes need to go into the
+right package and directory, certain stuff needs to be adjusted and table names
+need to be translated into their class names. This script will wrap all that
+behind a few simple options.
+
+In the most basic version, just give it a login and a table name, and it will
+load the schema information for this table and create the appropriate class
+files, or update them if already present.
+
+Each table has three associated files. A C<SL::DB::MetaSetup::*>
+class, which is a perl version of the schema definition, a
+C<SL::DB::*> class file and a C<SL::DB::Manager::*> manager class
+file. The first one will be updated if the schema changes, the second
+and third ones will only be created if it they do not exist.
+
+=head1 DATABASE NAMES AND TABLES
+
+If you want to generate the data for specific tables only then you
+have to list them on the command line. The format is
+C<db-name:table-name>. The part C<db-name:> is optional and defaults
+to C<KIVITENDO:> – which means the tables in the default kivitendo
+database.
+
+Valid database names are keys in the hash returned by
+L<SL::DB::Helper::Mappings/get_package_names>.
+
+=head1 OPTIONS
+
+=over 4
+
+=item C<--test-client, -t>
+
+Use the C<testing/database> to create a new testing database, and connect to
+the first client there. Overrides C<client>.
+
+If neither C<test-client> nor C<client> are set, the config key C<devel/client>
+will be used.
+
+=item C<--client, -c CLIENT>
+
+Provide a client whose database settings are used. C<CLIENT> can be either a
+database ID or a client's name.
+
+If neither C<test-client> nor C<client> are set, the config key C<devel/client>
+will be used.
+
+=item C<--all, -a>
+
+Process all tables from the database. Only those that are blacklistes in
+L<SL::DB::Helper::Mappings> are excluded.
+
+=item C<--db db>
+
+In combination with C<--all> causes all tables in the specific
+database to be processed, not in all databases.
+
+=item C<--no-commit, -n>
+
+=item C<--dry-run>
+
+Do not write back generated files. This will do everything as usual but not
+actually modify any file.
+
+=item C<--diff>
+
+Displays diff for selected file, if file is present and newer file is
+different. Beware, does not imply C<--no-commit>.
+
+=item C<--help, -h>
+
+Print this help.
+
+=item C<--quiet, -q>
+
+Does not print extra information, such as skipped files that were not
+changed and errors where the auto initialization failed.
+
+=back
+
+=head1 BUGS
+
+None yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>,
+Sven Schöling E<lt>s.schoeling@linet-services.deE<gt>
+
+=cut