1 package SL::DBUpgrade2::Base;
5 use parent qw(Rose::Object);
9 use English qw(-no_match_vars);
10 use File::Basename ();
13 use List::MoreUtils qw(uniq);
15 use Rose::Object::MakeMethods::Generic (
16 scalar => [ qw(dbh myconfig) ],
24 my $file_name = delete $params{file_name};
26 if (!eval { require $file_name }) {
27 delete $INC{$file_name};
31 my $package = delete $params{tag};
32 $package =~ s/[^a-zA-Z0-9_]+/_/g;
33 $package = "SL::DBUpgrade2::${package}";
35 $package->new(%params)->run;
39 my ($self, $msg) = @_;
41 die $::locale->text("Database update error:") . "<br>$msg<br>" . $self->db_errstr('DBI');
45 my ($self, $query, %params) = @_;
47 my $dbh = $params{dbh} || $self->dbh;
49 return if $dbh->do($query, undef, @{ $params{bind} || [] });
51 $self->db_error($query) unless $params{may_fail};
58 my ($self, $handle) = @_;
60 my $error = $handle ? $handle->errstr : $self->dbh->errstr;
62 return Encode::decode('utf-8', $error);
66 my ($self, $wanted_coa) = @_;
68 my ($have_coa) = selectrow_query($::form, $self->dbh, q{ SELECT count(*) FROM defaults WHERE coa = ? }, $wanted_coa);
76 my $query = q{ SELECT count(*)
77 FROM ar, ap, gl, invoice, acc_trans, customer, vendor, parts
79 my ($empty) = selectrow_query($::form, $self->dbh, $query);
84 sub add_print_templates {
85 my ($self, $src_dir, @files) = @_;
87 $::lxdebug->message(LXDebug::DEBUG1(), "add_print_templates: src_dir $src_dir files " . join(' ', @files));
90 croak "File '${src_dir}/$_' does not exist" unless -f "${src_dir}/$_";
93 my $template_dir = $::instance_conf->reload->get_templates;
94 $::lxdebug->message(LXDebug::DEBUG1(), "add_print_templates: template_dir $template_dir");
96 return 1 if !$template_dir;
98 foreach my $src_file (@files) {
99 my $dest_file = $template_dir . '/' . $src_file;
102 $::lxdebug->message(LXDebug::DEBUG1(), "add_print_templates: dest_file exists, skipping: ${dest_file}");
106 my $dest_dir = File::Basename::dirname($dest_file);
108 if ($dest_dir && !-d $dest_dir) {
109 File::Path::make_path($dest_dir) or die "Cannot create directory '${dest_dir}': $!";
112 File::Copy::copy($src_dir . '/' . $src_file, $dest_file) or die "Cannot copy '${src_dir}/${src_file}' to '${dest_file}': $!";
114 $::lxdebug->message(LXDebug::DEBUG1(), "add_print_templates: copied '${src_dir}/${src_file}' to '${dest_file}'");
120 sub drop_constraints {
121 my ($self, %params) = @_;
123 croak "Missing parameter 'table'" unless $params{table};
124 $params{type} ||= 'FOREIGN KEY';
125 $params{schema} ||= 'public';
127 my $constraints = $self->dbh->selectall_arrayref(<<SQL, undef, $params{type}, $params{schema}, $params{table});
128 SELECT constraint_name
129 FROM information_schema.table_constraints
130 WHERE (constraint_type = ?)
131 AND (table_schema = ?)
135 $self->db_query(qq|ALTER TABLE $params{schema}."$params{table}" DROP CONSTRAINT "${_}"|) for map { $_->[0] } @{ $constraints };
147 SL::DBUpgrade2::Base - Base class for Perl-based database upgrade files
151 Database scripts written in Perl must be derived from this class and
152 provide a method called C<run>.
154 The functions in this base class offer functionality for the upgrade
159 The following properties (which can be accessed with
160 C<$self-E<gt>property_name>) are available to the database upgrade
167 The database handle; an Instance of L<DBI>. It is connected, and a
168 transaction has been started right before the script (the method
169 L</run>)) was executed.
173 The stripped-down version of the C<%::myconfig> hash: this hash
174 reference only contains the database connection parameters applying to
175 the current database.
183 =item C<add_print_templates $source_dir, @files>
185 Adds (copies) new print templates to existing users. All existing
186 users in the authentication database are read. The listed C<@files>
187 are copied to each user's configured templates directory preserving
188 sub-directory structure (non-existing sub-directories will be
189 created). If a template with the same name exists it will be skipped.
191 The source file names must all be relative to the source directory
192 C<$source_dir>. This way only the desired sub-directories are created
193 in the users' template directories. Example:
195 $self->add_print_templates(
196 'templates/print/Standard',
197 qw(receipt.tex common.sty images/background.png)
200 Let's assume a user's template directory is
201 C<templates/big-money-inc>. The call above would trigger five actions:
205 =item 1. Create the directory C<templates/big-money-inc> if it doesn't
208 =item 2. Copy C<templates/print/Standard/receipt.tex> to
209 C<templates/big-money-inc/receipt.tex> if there's no such file in that
212 =item 3. Copy C<templates/print/Standard/common.sty> to
213 C<templates/big-money-inc/common.sty> if there's no such file in that
216 =item 4. Create the directory C<templates/big-money-inc/images> if it
219 =item 5. Copy C<templates/print/Standard/images/background.png> to
220 C<templates/big-money-inc/images/background.png> if there's no such
221 file in that directory.
225 =item C<check_coa $coa_name>
227 Returns trueish if the database uses the chart of accounts named
230 =item C<db_error $message>
232 Outputs an error message C<$message> to the user and aborts execution.
234 =item C<db_query $query, %params>
236 Executes an SQL query. The following parameters are supported:
242 What the method does if the query fails depends on this parameter. If
243 it is falsish (the default) then the method will simply die outputting
244 the error message via L</db_error>. If C<may_fail> is trueish then the
245 current transaction will be rolled back, a new one will be started.
249 An optional array reference containing bind parameter for the query.
253 The database handle to use. If undefined then C<$self-E<gt>dbh> will
258 =item C<db_errstr [$handle]>
260 Returns the last database from C<$handle> error message encoded in
261 Perl's internal encoding. The PostgreSQL DBD leaves the UTF-8 flag off
262 for error messages even if the C<pg_enable_utf8> attribute is set.
264 C<$handle> is optional and can be one of three things:
268 =item 1. A database or statement handle. In that case
269 C<$handle-E<gt>errstr> is used.
271 =item 2. The string 'DBI'. In that case C<$DBI::errstr> is used.
273 =item 3. If it is undefined then C<$self-E<gt>dbh-E<gt>errstr> is
278 =item C<drop_constraints %params>
280 Drops all constraints of a type (e.g. foreign keys) on a table. One
281 parameter is mandatory: C<table>. Optional parameters include:
285 =item * C<schema> -- if missing defaults to C<public>
287 =item * C<type> -- if missing defaults to C<FOREIGN KEY>. Must be one of
288 the values contained in the C<information_schema.table_constraints>
289 view in the C<constraint_type> column.
293 =item C<execute_script>
295 Executes a named database upgrade script. This function is not
296 supposed to be called from an upgrade script. Instead, the upgrade
297 manager L<SL::DBUpgrade2> uses it in order to execute the actual
298 database upgrade scripts.
300 =item C<is_coa_empty>
302 Returns trueish if no transactions have been recorded in the table
307 This method is the entry point for the actual upgrade. Each upgrade
308 script must provide this method.
318 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>