[Dbix-class] Deployment seems to destroy CHARACTER SET settings on MySQL tables

Lianna Eeftinck liannaee at gmail.com
Tue Aug 12 14:41:01 GMT 2014


package MyApp::Schema::Loader::DBI::mysql::ExtraColumnInfo;
use strict;
use warnings;
use base 'DBIx::Class::Schema::Loader::DBI::mysql';
use mro 'c3';

my $mysql_text_types = qr/^(?: var(?:char)? | char(?:acter)? |
(?:tiny|medium|long)?text )$/msxi;

sub new {
    return shift->next::method( @_ );
}

sub _extra_column_info {
    my ( $self, $table, $col, $info, $dbi_info ) = @_;

    my $extra_info = $self->next::method( $table, $col, $info, $dbi_info );

    if ( $info->{data_type} =~ /$mysql_text_types/msxi ) {
        my ( $character_set_name, $collation_name ) = eval {
            $self->dbh->selectrow_array( qq{
               SELECT character_set_name, collation_name
               FROM information_schema.columns
               WHERE table_name = ? AND lower(column_name) = ?
            }, {}, $table->name, lc( $col ) );
        };

        if ( my $has_information_schema = not $@ ) {
            $extra_info->{ extra }{ mysql_collate } = $collation_name;
            $extra_info->{ extra }{ mysql_charset } = $character_set_name;
        }
    }

    return $extra_info;
}

1;


And include it in the schema loader options too:

loader_class => 'MyApp::Schema::Loader::DBI::mysql::ExtraColumnInfo'

It's actually reading the database where this information gets lost, it's
never stored in the YAML generated by DBIx::Schema::Loader, so it won't be
output properly either until it is added.

-- Lianna



On 10 August 2014 15:32, Matija Grabnar <matija at serverflow.com> wrote:

> I am developing a Catalyst application that uses DBIx::Class. I thought I
> would do things right and use DBIx::Class::DeploymentHandler right from the
> start.
> I was able to get it to deploy and upgrade my tables very nicely.
> However, I have run into a show stopper now:
>
> The character set settings of tables and strings are not preserved. That
> means that if I declare a table like this:
>
> create table graph_category (
> id serial primary key,
> category varchar(190) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci,
> unique index i_graph_category_category(category)
> ) engine=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
>
> and then do
> dbicdump -o dump_directory=./lib \
>            -o debug=1 \
>            MyDB \
>            'dbi:mysql:dbname=mydb' \
>            someusername \
>            notthepassword
>
>
> And then a script containing
>  my $dh = DBIx::Class::DeploymentHandler->new(
>      {
>          schema              => $schema,
>          script_directory    => "$FindBin::Bin/../dbicdh",
>          databases           => 'MySQL',
>          sql_translator_args => { add_drop_table => 1 },
>          force_overwrite     => $force_overwrite,
>      }
>     );
>
> $dh->prepare_install;
> $dh->install;
>
> The table in the database will become:
>
> CREATE TABLE `graph_category` (
>   `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
>   `category` varchar(190) DEFAULT NULL,
>   PRIMARY KEY (`id`),
>   UNIQUE KEY `i_graph_category_category` (`category`)
> ) ENGINE=InnoDB DEFAULT CHARSET=latin1
>
> In other words, all the character set info has disappeared. Since the
> requirements specify a lot of UTF8 work, I find that quite distressing. And
> in production, I'm afraid it could lead to data corruption.
>
> Does anybody know of a way to avoid this problem (short of discarding
> DeploymentHandler altogether)?
>
> _______________________________________________
> List: http://lists.scsys.co.uk/cgi-bin/mailman/listinfo/dbix-class
> IRC: irc.perl.org#dbix-class
> SVN: http://dev.catalyst.perl.org/repos/bast/DBIx-Class/
> Searchable Archive: http://www.grokbase.com/group/
> dbix-class at lists.scsys.co.uk
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.scsys.co.uk/pipermail/dbix-class/attachments/20140812/42bbc8ae/attachment.html>


More information about the DBIx-Class mailing list