X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=blobdiff_plain;f=lib%2FDBIx%2FClass%2FStorage%2FDBI%2FSybase.pm;h=6c0736983c77fa8e1b621be7425b8411ef208c84;hb=c9d9c67046115c4717b9ad49532b66d82d135310;hp=cc8a0cc51bf0ed08a49d94490b27c04b173b57da;hpb=9b3dabe0c35b6dafdfec559d594e95d5131e84b5;p=dbsrgits%2FDBIx-Class.git diff --git a/lib/DBIx/Class/Storage/DBI/Sybase.pm b/lib/DBIx/Class/Storage/DBI/Sybase.pm index cc8a0cc..6c07369 100644 --- a/lib/DBIx/Class/Storage/DBI/Sybase.pm +++ b/lib/DBIx/Class/Storage/DBI/Sybase.pm @@ -4,15 +4,20 @@ use strict; use warnings; use base qw/ - DBIx::Class::Storage::DBI::Sybase::Base - DBIx::Class::Storage::DBI + DBIx::Class::Storage::DBI::Sybase::Common + DBIx::Class::Storage::DBI::AutoCast /; use mro 'c3'; use Carp::Clan qw/^DBIx::Class/; +use List::Util (); + +__PACKAGE__->mk_group_accessors('simple' => + qw/_identity _blob_log_on_update unsafe_insert _insert_dbh/ +); =head1 NAME -DBIx::Class::Storage::DBI::Sybase - Storage::DBI subclass for Sybase +DBIx::Class::Storage::DBI::Sybase - Sybase support for DBIx::Class =head1 SYNOPSIS @@ -27,28 +32,27 @@ will be reblessed to L. You can also enable that driver explicitly, see the documentation for more details. With this driver there is unfortunately no way to get the C -without doing a C. This is done safely in a transaction +(locking the table.) The transaction can be turned off if concurrency is not an +issue, or you don't need the C value, see +L. But your queries will be cached. -A recommended L settings: +A recommended L setting: - on_connect_call => [['datetime_setup'], [blob_setup => log_on_update => 0]] + on_connect_call => [['datetime_setup'], ['blob_setup', log_on_update => 0]] =head1 METHODS =cut -__PACKAGE__->mk_group_accessors('simple' => - qw/_blob_log_on_update/ -); - sub _rebless { my $self = shift; if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') { my $dbtype = eval { - @{$self->dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2] + @{$self->_get_dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2] } || ''; my $exception = $@; @@ -58,38 +62,82 @@ sub _rebless { if (!$exception && $dbtype && $self->load_optional_class($subclass)) { bless $self, $subclass; $self->_rebless; - } else { - # real Sybase - if (not $self->dbh->{syb_dynamic_supported}) { - $self->ensure_class_loaded('DBIx::Class::Storage::DBI::Sybase::NoBindVars'); - bless $self, 'DBIx::Class::Storage::DBI::Sybase::NoBindVars'; + } else { # real Sybase + my $no_bind_vars = 'DBIx::Class::Storage::DBI::Sybase::NoBindVars'; + + if ($self->using_freetds) { + carp <<'EOF' unless $ENV{DBIC_SYBASE_FREETDS_NOWARN}; + +You are using FreeTDS with Sybase. + +We will do our best to support this configuration, but please consider this +support experimental. + +TEXT/IMAGE columns will definitely not work. + +You are encouraged to recompile DBD::Sybase with the Sybase Open Client libraries +instead. + +See perldoc DBIx::Class::Storage::DBI::Sybase for more details. + +To turn off this warning set the DBIC_SYBASE_FREETDS_NOWARN environment +variable. +EOF + if (not $self->_typeless_placeholders_supported) { + if ($self->_placeholders_supported) { + $self->auto_cast(1); + } else { + $self->ensure_class_loaded($no_bind_vars); + bless $self, $no_bind_vars; + $self->_rebless; + } + } + + $self->set_textsize; # based on LongReadLen in connect_info + + } + elsif (not $self->_get_dbh->{syb_dynamic_supported}) { + # not necessarily FreeTDS, but no placeholders nevertheless + $self->ensure_class_loaded($no_bind_vars); + bless $self, $no_bind_vars; $self->_rebless; + } elsif (not $self->_typeless_placeholders_supported) { +# this is highly unlikely, but we check just in case + $self->auto_cast(1); } - $self->_set_maxConnect; + + $self->_set_max_connect(256); } } } -sub _set_maxConnect { +# Make sure we have CHAINED mode turned on if AutoCommit is off in non-FreeTDS +# DBD::Sybase (since we don't know how DBD::Sybase was compiled.) If however +# we're using FreeTDS, CHAINED mode turns on an implicit transaction which we +# only want when AutoCommit is off. +sub _populate_dbh { my $self = shift; - my $dsn = $self->_dbi_connect_info->[0]; - - return if ref($dsn) eq 'CODE'; + $self->next::method(@_); - if ($dsn !~ /maxConnect=/) { - $self->_dbi_connect_info->[0] = "$dsn;maxConnect=256"; - my $connected = defined $self->_dbh; - $self->disconnect; - $self->ensure_connected if $connected; + if (not $self->using_freetds) { + $self->_dbh->{syb_chained_txn} = 1; + } else { + if ($self->_dbh_autocommit) { + $self->_dbh->do('SET CHAINED OFF'); + } else { + $self->_dbh->do('SET CHAINED ON'); + } } + + $self->_insert_dbh($self->_connect(@{ $self->_dbi_connect_info })); } =head2 connect_call_blob_setup Used as: - on_connect_call => [ [ blob_setup => log_on_update => 0 ] ] + on_connect_call => [ [ 'blob_setup', log_on_update => 0 ] ] Does C<< $dbh->{syb_binary_images} = 1; >> to return C data as raw binary instead of as a hex string. @@ -114,43 +162,204 @@ sub connect_call_blob_setup { if exists $args{log_on_update}; } +=head2 connect_call_unsafe_insert + +With placeholders enabled, inserts are done in a transaction so that there are +no concurrency issues with getting the inserted identity value using +C