support for unicode Firebird data types
[dbsrgits/DBIx-Class-Schema-Loader.git] / lib / DBIx / Class / Schema / Loader / DBI / InterBase.pm
index 19f332f..8490859 100644 (file)
@@ -2,13 +2,13 @@ package DBIx::Class::Schema::Loader::DBI::InterBase;
 
 use strict;
 use warnings;
-use namespace::autoclean;
-use Class::C3;
+use mro 'c3';
 use base qw/DBIx::Class::Schema::Loader::DBI/;
 use Carp::Clan qw/^DBIx::Class/;
 use List::Util 'first';
+use namespace::clean;
 
-our $VERSION = '0.07000';
+our $VERSION = '0.07010';
 
 =head1 NAME
 
@@ -21,16 +21,16 @@ See L<DBIx::Class::Schema::Loader> and L<DBIx::Class::Schema::Loader::Base>.
 
 =head1 COLUMN NAME CASE ISSUES
 
-By default column names from unquoted DDL will be generated in uppercase, as
-that is the only way they will work with quoting on.
+By default column names from unquoted DDL will be generated in lowercase, for
+consistency with other backends. 
 
-See the L<preserve_case|DBIx::Class::Schema::Loader::Base/preserve_case> option
-to false if you would like to have lowercase column names.
+Set the L<preserve_case|DBIx::Class::Schema::Loader::Base/preserve_case> option
+to true if you would like to have column names in the internal case, which is
+uppercase for DDL that uses unquoted identifiers.
 
-Setting this option is a good idea if your DDL uses unquoted identifiers and
-you will not use quoting (the
-L<quote_char|DBIx::Class::Storage::DBI/quote_char> option in
-L<connect_info|DBIx::Class::Storage::DBI/connect_info>.)
+Do not use quoting (the L<quote_char|DBIx::Class::Storage::DBI/quote_char>
+option in L<connect_info|DBIx::Class::Storage::DBI/connect_info> when in the
+default C<< preserve_case => 0 >> mode.
 
 Be careful to also not use any SQL reserved words in your DDL.
 
@@ -40,9 +40,6 @@ names) in your Result classes that will only work with quoting off.
 Mixed-case table and column names will be ignored when this option is on and
 will not work with quoting turned off.
 
-B<NOTE:> This option used to be called C<unquoted_ddl> but has been removed in
-favor of the more generic option.
-
 =cut
 
 sub _setup {
@@ -53,23 +50,23 @@ sub _setup {
     if (not defined $self->preserve_case) {
         warn <<'EOF';
 
-WARNING: Assuming mixed-case Firebird DDL, see
+WARNING: Assuming unquoted Firebird DDL, see
 perldoc DBIx::Class::Schema::Loader::DBI::InterBase
 and the 'preserve_case' option in
 perldoc DBIx::Class::Schema::Loader::Base
 for more information.
 
 EOF
-        $self->preserve_case(1);
+        $self->preserve_case(0);
     }
 
-    $self->schema->storage->sql_maker->name_sep('.');
-
     if ($self->preserve_case) {
         $self->schema->storage->sql_maker->quote_char('"');
+        $self->schema->storage->sql_maker->name_sep('.');
     }
     else {
         $self->schema->storage->sql_maker->quote_char(undef);
+        $self->schema->storage->sql_maker->name_sep(undef);
     }
 }
 
@@ -195,7 +192,7 @@ EOF
 
 # fix up types
         $sth = $dbh->prepare(<<'EOF');
-SELECT f.rdb$field_precision, f.rdb$field_scale, f.rdb$field_type, f.rdb$field_sub_type, t.rdb$type_name, st.rdb$type_name
+SELECT f.rdb$field_precision, f.rdb$field_scale, f.rdb$field_type, f.rdb$field_sub_type, f.rdb$character_set_id, f.rdb$character_length, t.rdb$type_name, st.rdb$type_name
 FROM rdb$fields f
 JOIN rdb$relation_fields rf ON rf.rdb$field_source = f.rdb$field_name
 LEFT JOIN rdb$types t  ON f.rdb$field_type     = t.rdb$type  AND t.rdb$field_name  = 'RDB$FIELD_TYPE'
@@ -204,7 +201,7 @@ WHERE rf.rdb$relation_name = ?
     AND rf.rdb$field_name  = ?
 EOF
         $sth->execute($table, $self->_uc($column));
-        my ($precision, $scale, $type_num, $sub_type_num, $type_name, $sub_type_name) = $sth->fetchrow_array;
+        my ($precision, $scale, $type_num, $sub_type_num, $char_set_id, $char_length, $type_name, $sub_type_name) = $sth->fetchrow_array;
         $scale = -$scale if $scale && $scale < 0;
 
         if ($type_name && $sub_type_name) {
@@ -228,7 +225,12 @@ EOF
                     $info->{data_type} = 'blob';
                 }
                 elsif ($sub_type_name eq 'TEXT') {
-                    $info->{data_type} = 'blob sub_type text';
+                    if ($char_set_id == 3) {
+                        $info->{data_type} = 'blob sub_type text character set unicode_fss';
+                    }
+                    else {
+                        $info->{data_type} = 'blob sub_type text';
+                    }
                 }
             }
         }
@@ -257,16 +259,22 @@ EOF
         elsif ($info->{data_type} eq 'character') {
             $info->{data_type} = 'char';
         }
+        elsif ($info->{data_type} eq 'float') {
+            $info->{data_type} = 'real';
+        }
         elsif ($info->{data_type} eq 'int64' || $info->{data_type} eq '-9581') {
             # the constant is just in case, the query should pick up the type
             $info->{data_type} = 'bigint';
         }
 
-        # DBD::InterBase sets scale to '0' for some reason for char types
-        if ($info->{data_type} =~ /^(?:char|varchar)\z/ && ref($info->{size}) eq 'ARRAY') {
-            $info->{size} = $info->{size}[0];
+        if ($info->{data_type} =~ /^(?:char|varchar)\z/) {
+            $info->{size} = $char_length;
+
+            if ($char_set_id == 3) {
+                $info->{data_type} .= '(x) character set unicode_fss';
+            }
         }
-        elsif ($info->{data_type} !~ /^(?:char|varchar|numeric|decimal)\z/) {
+        elsif ($info->{data_type} !~ /^(?:numeric|decimal)\z/) {
             delete $info->{size};
         }
 
@@ -287,7 +295,7 @@ EOF
                 $info->{default_value} = $quoted;
             }
             else {
-                $info->{default_value} = $def =~ /^\d/ ? $def : \$def;
+                $info->{default_value} = $def =~ /^-?\d/ ? $def : \$def;
             }
         }