From: Peter Rabbitson Date: Fri, 23 Mar 2012 09:38:18 +0000 (+0100) Subject: Centralize (and privatize) handling of freetds driver/version detection X-Git-Tag: v0.08197~69 X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=aca3b4c3cd5df48ab0dd98ff8e54f61a1ea27b8b;p=dbsrgits%2FDBIx-Class.git Centralize (and privatize) handling of freetds driver/version detection --- diff --git a/lib/DBIx/Class/Storage/DBI/ODBC.pm b/lib/DBIx/Class/Storage/DBI/ODBC.pm index fec6613..65bc811 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC.pm @@ -28,6 +28,29 @@ sub _rebless { } } +# Whether or not we are connecting via the freetds ODBC driver. +sub _using_freetds { + my $self = shift; + + my $dsn = $self->_dbi_connect_info->[0]; + + return 1 if ( + ( (! ref $dsn) and $dsn =~ /driver=FreeTDS/i) + or + ( ($self->_dbh_get_info('SQL_DRIVER_NAME')||'') =~ /tdsodbc/i ) + ); + + return 0; +} + +# Either returns the FreeTDS version via which we are connecting, 0 if can't +# be determined, or undef otherwise +sub _using_freetds_version { + my $self = shift; + return undef unless $self->_using_freetds; + return $self->_dbh_get_info('SQL_DRIVER_VER') || 0; +} + 1; =head1 NAME diff --git a/lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm b/lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm index 8888a8e..e17715c 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC/DB2_400_SQL.pm @@ -4,8 +4,8 @@ use strict; use warnings; use base qw/ - DBIx::Class::Storage::DBI::DB2 DBIx::Class::Storage::DBI::ODBC + DBIx::Class::Storage::DBI::DB2 /; use mro 'c3'; diff --git a/lib/DBIx/Class/Storage/DBI/ODBC/Firebird.pm b/lib/DBIx/Class/Storage/DBI/ODBC/Firebird.pm index 133dcc1..9067290 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC/Firebird.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC/Firebird.pm @@ -2,7 +2,10 @@ package DBIx::Class::Storage::DBI::ODBC::Firebird; use strict; use warnings; -use base 'DBIx::Class::Storage::DBI::Firebird::Common'; +use base qw/ + DBIx::Class::Storage::DBI::ODBC + DBIx::Class::Storage::DBI::Firebird::Common +/; use mro 'c3'; use Try::Tiny; use namespace::clean; diff --git a/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm b/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm index afd51f3..c11634d 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC/Microsoft_SQL_Server.pm @@ -2,7 +2,10 @@ package DBIx::Class::Storage::DBI::ODBC::Microsoft_SQL_Server; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI::MSSQL/; +use base qw/ + DBIx::Class::Storage::DBI::ODBC + DBIx::Class::Storage::DBI::MSSQL +/; use mro 'c3'; use Scalar::Util 'reftype'; use Try::Tiny; @@ -124,7 +127,7 @@ sub connect_call_use_mars { } if ($dsn !~ /MARS_Connection=/) { - if ($self->using_freetds) { + if ($self->_using_freetds) { $self->throw_exception('FreeTDS does not support MARS at the time of ' .'writing.'); } @@ -226,7 +229,7 @@ sub _run_connection_actions { $self->throw_exception ( 'Your drivers do not seem to support dynamic cursors (odbc_cursortype => 2).' . ( - $self->using_freetds + $self->_using_freetds ? ' If you are using FreeTDS, make sure to set tds_version to 8.0 or greater.' : '' ) @@ -235,7 +238,7 @@ sub _run_connection_actions { $self->_using_dynamic_cursors(1); $self->_identity_method('@@identity'); - $self->_no_scope_identity_query($self->using_freetds); + $self->_no_scope_identity_query($self->_using_freetds); } else { $self->_using_dynamic_cursors(0); @@ -247,11 +250,11 @@ sub _run_connection_actions { $self->next::method (@_); # freetds is too damn broken, some fixups - if ($self->using_freetds) { + if ($self->_using_freetds) { # no dynamic cursors starting from 0.83 if ($self->_using_dynamic_cursors) { - my $fv = $self->_dbh_get_info('SQL_DRIVER_VER'); + my $fv = $self->_using_freetds_version || 999; # assume large if can't be determined $self->throw_exception( 'Dynamic cursors (odbc_cursortype => 2) are not supported with FreeTDS > 0.82 ' . "(you have $fv). Please hassle FreeTDS authors to fix the outstanding bugs in " @@ -297,26 +300,6 @@ sub connect_call_use_server_cursors { $self->_get_dbh->{odbc_SQL_ROWSET_SIZE} = $sql_rowset_size; } -=head2 using_freetds - -Tries to determine, to the best of our ability, whether or not you are using the -FreeTDS driver with L. - -=cut - -sub using_freetds { - my $self = shift; - - my $dsn = $self->_dbi_connect_info->[0]; - - $dsn = '' if ref $dsn eq 'CODE'; - - return 1 if $dsn =~ /driver=FreeTDS/i - || ($self->_dbh_get_info('SQL_DRIVER_NAME')||'') =~ /tdsodbc/i; - - return 0; -} - 1; =head1 AUTHOR diff --git a/lib/DBIx/Class/Storage/DBI/ODBC/SQL_Anywhere.pm b/lib/DBIx/Class/Storage/DBI/ODBC/SQL_Anywhere.pm index d40029e..0a6bd1a 100644 --- a/lib/DBIx/Class/Storage/DBI/ODBC/SQL_Anywhere.pm +++ b/lib/DBIx/Class/Storage/DBI/ODBC/SQL_Anywhere.pm @@ -2,7 +2,10 @@ package DBIx::Class::Storage::DBI::ODBC::SQL_Anywhere; use strict; use warnings; -use base qw/DBIx::Class::Storage::DBI::SQLAnywhere/; +use base qw/ + DBIx::Class::Storage::DBI::ODBC + DBIx::Class::Storage::DBI::SQLAnywhere +/; use mro 'c3'; 1; diff --git a/lib/DBIx/Class/Storage/DBI/Sybase.pm b/lib/DBIx/Class/Storage/DBI/Sybase.pm index 901cf0a..32f7996 100644 --- a/lib/DBIx/Class/Storage/DBI/Sybase.pm +++ b/lib/DBIx/Class/Storage/DBI/Sybase.pm @@ -49,7 +49,7 @@ sub _init { # once the driver is determined see if we need to insert the DBD::Sybase w/ FreeTDS fixups # this is a dirty version of "instance role application", \o/ DO WANT Moo \o/ my $self = shift; - if (! $self->isa('DBIx::Class::Storage::DBI::Sybase::FreeTDS') and $self->using_freetds) { + if (! $self->isa('DBIx::Class::Storage::DBI::Sybase::FreeTDS') and $self->_using_freetds) { require DBIx::Class::Storage::DBI::Sybase::FreeTDS; my @isa = @{mro::get_linear_isa(ref $self)}; @@ -117,19 +117,21 @@ sub _set_max_connect { } } -=head2 using_freetds - -Whether or not L was compiled against FreeTDS. If false, it means -the Sybase OpenClient libraries were used. - -=cut - -sub using_freetds { +# Whether or not DBD::Sybase was compiled against FreeTDS. If false, it means +# the Sybase OpenClient libraries were used. +sub _using_freetds { my $self = shift; - return ($self->_get_dbh->{syb_oc_version}||'') =~ /freetds/i; } +# Either returns the FreeTDS version against which DBD::Sybase was compiled, +# 0 if can't be determined, or undef otherwise +sub _using_freetds_version { + my $inf = shift->_get_dbh->{syb_oc_version}; + return undef unless ($inf||'') =~ /freetds/i; + return $inf =~ /v([0-9\.]+)/ ? $1 : 0; +} + 1; =head1 AUTHORS diff --git a/lib/DBIx/Class/Storage/DBI/Sybase/ASE.pm b/lib/DBIx/Class/Storage/DBI/Sybase/ASE.pm index 25c407a..17a7690 100644 --- a/lib/DBIx/Class/Storage/DBI/Sybase/ASE.pm +++ b/lib/DBIx/Class/Storage/DBI/Sybase/ASE.pm @@ -73,7 +73,7 @@ sub _rebless { my $no_bind_vars = __PACKAGE__ . '::NoBindVars'; - if ($self->using_freetds) { + if ($self->_using_freetds) { carp_once <<'EOF' unless $ENV{DBIC_SYBASE_FREETDS_NOWARN}; You are using FreeTDS with Sybase. @@ -202,7 +202,7 @@ sub _run_connection_actions { } $self->_dbh->{syb_chained_txn} = 1 - unless $self->using_freetds; + unless $self->_using_freetds; $self->next::method(@_); } @@ -804,7 +804,7 @@ sub _insert_blobs { $sth->func('ct_finish_send') or die $sth->errstr; } catch { - if ($self->using_freetds) { + if ($self->_using_freetds) { $self->throw_exception ( "TEXT/IMAGE operation failed, probably because you are using FreeTDS: $_" ); @@ -958,7 +958,7 @@ L. Sybase ASE for Linux (which comes with the Open Client libraries) may be downloaded here: L. -To see if you're using FreeTDS check C<< $schema->storage->using_freetds >>, or run: +To see if you're using FreeTDS run: perl -MDBI -le 'my $dbh = DBI->connect($dsn, $user, $pass); print $dbh->{syb_oc_version}' diff --git a/t/746mssql.t b/t/746mssql.t index 403d75c..0193753 100644 --- a/t/746mssql.t +++ b/t/746mssql.t @@ -58,7 +58,7 @@ my %opts = ( { opts => { on_connect_call => 'use_mars' } }, use_dynamic_cursors => { opts => { on_connect_call => 'use_dynamic_cursors' }, - required => $schema->storage->using_freetds ? 0 : 1, + required => $schema->storage->_using_freetds ? 0 : 1, }, use_server_cursors => { opts => { on_connect_call => 'use_server_cursors' } }, @@ -511,7 +511,7 @@ SQL TODO: { my $freetds_and_dynamic_cursors = 1 if $opts_name eq 'use_dynamic_cursors' && - $schema->storage->using_freetds; + $schema->storage->_using_freetds; local $TODO = 'these tests fail on freetds with dynamic cursors for some reason' diff --git a/t/746sybase.t b/t/746sybase.t index 5936e47..43e2ab5 100644 --- a/t/746sybase.t +++ b/t/746sybase.t @@ -335,7 +335,7 @@ SQL # mostly stolen from the blob stuff Nniuq wrote for t/73oracle.t SKIP: { skip 'TEXT/IMAGE support does not work with FreeTDS', 22 - if $schema->storage->using_freetds; + if $schema->storage->_using_freetds; my $dbh = $schema->storage->_dbh; { @@ -359,7 +359,7 @@ SQL my $maxloblen = length $binstr{'large'}; - if (not $schema->storage->using_freetds) { + if (not $schema->storage->_using_freetds) { $dbh->{'LongReadLen'} = $maxloblen * 2; } else { $dbh->do("set textsize ".($maxloblen * 2));