I have a MySQL (MariaDB) database with some tables inside. All table names have some prefix, like app_author
, app_album
, app_track
(in fact, there are different tables, but an example with author-album-track should be usable here). I use dbicdump
to dump my DB structure. The problem is, generated result sets are named AppAuthor
, AppAlbum
, AppTrack
. My defined relations between a table to referenced table are named by columns in those tables, the other way is named by tables.
Let's create some tables to ilustrate this:
create table app_author (
id int not null,
name varchar(255),
primary key(id)
);
create table app_album (
id int not null,
name varchar(255),
author int not null references app_author (id),
primary key (id)
);
create table app_track (
id int not null,
name varchar(255),
album int not null references app_album (id),
primary key(id)
);
And example usage in Perl would be like this:
my $album = resultset("AppAlbum")->search(...)->single; # [1]
my $author = $album->author;
for my $track ($album->app_tracks) { # [2]
...
}
My questions:
Is there possibility to tell dbicdump to ignore those "app_" prefixes and create result sets named without it, e.g. Author
, Album
, Track
?
How to automatically create relations without "app_" prefix?
I know I could create my result sets by hand, but then I would need to synchronize DB to my DB model by hand each time I change DB (which is quite often in current stage of application implementation). I would prefer some configuration to dbicdump to automate this, but I was unable to find this in docs.
Currently I use this in my code:
my $PREFIX = "app_";
...
my $album = resultset("${PREFIX}Album")->search(...)
And also in my result set classes generated by dbicdump I always add "correct" relations like this to be able to use $album->tracks
:
package MyApp::DB::Result::AppAlbum;
...
# Created by DBIx::Class::Schema::Loader v0.07052 @ 2024-05-21 11:41:20
# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:TvdTvR2Iuo++AHLi0SHc3g
sub tracks ($self)
{
return $self->app_tracks;
}
Thank you for your advices.
Finally I found the working solution. We need 2 files:
File db_dump.sh
to run dbicdump
in turn with desired configuration:
#!/bin/sh
export PERL5LIB=../perl5lib/lib/perl5
../perl5lib/bin/dbicdump \
-o config_file=./db_dump.pm \
-o dump_directory=./lib \
MyApp::DB \
dbi:mysql:database=mydb dbuser dbpass \
'{ quote_char => "`" }'
File db_dump.pm
for configuration of dbicdump
. I included versions with hashref and subs (my preferred versions):
{
constraint => '^(?:user|session|app_.*)$',
moniker_map => sub {
my ($table, $moniker, $callable) = @_;
#return "$table"; # $moniker = $table_name
$moniker =~ s/^App//;
return $moniker;
},
# moniker_map => {
# app_author => "Author",
# app_album => "Album",
# app_track => "Track",
# },
rel_name_map => sub {
my ($a, $coderef) = @_;
return unless $a->{type} eq "has_many";
$a->{name} =~ s/^app_//;
return $a->{name};
},
# rel_name_map => {
# Author => { # name all changes to Author's relationships
# app_albums => "albums",
# },
# Album => { # name all changes to Album's relationships
# app_tracks => "tracks",
# },
# },
}
Now run db_dump.sh
and all classes are dumped from DB and placed as respective files in ./lib/MyApp/DB/Result/
.
Some random notes:
If you read DBIx::Class' docs, a moniker is the name of result set, e.g. resultset($moniker)->search()...
-o dump_directory=./lib
This should be specified on command line, specifying it in
config file isn't working
constraint
Regex to specify tables to dump.
moniker_map
1st form (hashref with schema) - I was unable to get it working.
2nd form (hashref without schema) - Should enumerate all interresting
tables. Works nicely.
3rd form (coderef) - Just return desired moniker for respective table.
Or undef for default. Didn't understand the part with callable coderef.
Easy to just strip unwanted prefixes.
rel_name_map
Hashrefs with monikers works. But specifying all of changes... too
much work.
The coderef version is the way to go for me.
For more, read https://metacpan.org/pod/DBIx::Class::Schema::Loader::Base, everything is there. In fact, too much info in there :)