1 package DBIx::Class::Storage::DBI::Sybase;
7 DBIx::Class::Storage::DBI::Sybase::Base
8 DBIx::Class::Storage::DBI
11 use Carp::Clan qw/^DBIx::Class/;
15 DBIx::Class::Storage::DBI::Sybase - Sybase support for DBIx::Class
19 This subclass supports L<DBD::Sybase> for real Sybase databases. If you are
20 using an MSSQL database via L<DBD::Sybase>, your storage will be reblessed to
21 L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
25 If your version of Sybase does not support placeholders, then your storage
26 will be reblessed to L<DBIx::Class::Storage::DBI::Sybase::NoBindVars>. You can
27 also enable that driver explicitly, see the documentation for more details.
29 With this driver there is unfortunately no way to get the C<last_insert_id>
30 without doing a C<select max(col)>.
32 But your queries will be cached.
34 You need a version of L<DBD::Sybase> compiled with the Sybase OpenClient
35 libraries, B<NOT> FreeTDS, for placeholder support. Otherwise your storage will
36 be automatically reblessed into C<::NoBindVars>.
38 A recommended L<DBIx::Class::Storage::DBI/connect_info> setting:
40 on_connect_call => [['datetime_setup'], ['blob_setup', log_on_update => 0]]
46 __PACKAGE__->mk_group_accessors('simple' =>
47 qw/_blob_log_on_update/
53 if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') {
55 @{$self->dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2]
60 my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
62 if (!$exception && $dbtype && $self->load_optional_class($subclass)) {
63 bless $self, $subclass;
65 } else { # real Sybase
66 my $no_bind_vars = 'DBIx::Class::Storage::DBI::Sybase::NoBindVars';
68 if ($self->_using_freetds) {
71 Your version of Sybase potentially supports placeholders and query caching,
72 however you seem to be using FreeTDS which does not (yet?) support this.
74 Please recompile DBD::Sybase with the Sybase OpenClient libraries if you want
77 TEXT/IMAGE column support will also not work under FreeTDS.
79 See perldoc DBIx::Class::Storage::DBI::Sybase for more details.
81 $self->ensure_class_loaded($no_bind_vars);
82 bless $self, $no_bind_vars;
86 if (not $self->dbh->{syb_dynamic_supported}) {
87 $self->ensure_class_loaded($no_bind_vars);
88 bless $self, $no_bind_vars;
92 $self->_set_maxConnect;
100 return $self->_dbh->{syb_oc_version} =~ /freetds/i;
103 sub _set_maxConnect {
106 my $dsn = $self->_dbi_connect_info->[0];
108 return if ref($dsn) eq 'CODE';
110 if ($dsn !~ /maxConnect=/) {
111 $self->_dbi_connect_info->[0] = "$dsn;maxConnect=256";
112 my $connected = defined $self->_dbh;
114 $self->ensure_connected if $connected;
118 =head2 connect_call_blob_setup
122 on_connect_call => [ [ 'blob_setup', log_on_update => 0 ] ]
124 Does C<< $dbh->{syb_binary_images} = 1; >> to return C<IMAGE> data as raw binary
125 instead of as a hex string.
129 Also sets the C<log_on_update> value for blob write operations. The default is
130 C<1>, but C<0> is better if your database is configured for it.
133 L<DBD::Sybase/Handling_IMAGE/TEXT_data_with_syb_ct_get_data()/syb_ct_send_data()>.
137 sub connect_call_blob_setup {
140 my $dbh = $self->_dbh;
141 $dbh->{syb_binary_images} = 1;
143 $self->_blob_log_on_update($args{log_on_update})
144 if exists $args{log_on_update};
150 $type && $type =~ /(?:text|image|lob|bytea|binary|memo)/i;
153 ## This will be useful if we ever implement BLOB filehandle inflation and will
154 ## need to use the API, but for now it isn't.
156 #sub order_columns_for_select {
157 # my ($self, $source, $columns) = @_;
159 # my (@non_blobs, @blobs);
161 # for my $col (@$columns) {
162 # if ($self->_is_lob_type($source->column_info($col)->{data_type})) {
165 # push @non_blobs, $col;
169 # croak "cannot select more than a one TEXT/IMAGE column at a time"
172 # return (@non_blobs, @blobs);
175 # override to handle TEXT/IMAGE
177 my ($self, $source, $to_insert) = splice @_, 0, 3;
179 my $blob_cols = $self->_remove_blob_cols($source, $to_insert);
181 my $updated_cols = $self->next::method($source, $to_insert, @_);
183 $self->_insert_blobs($source, $blob_cols, $to_insert) if %$blob_cols;
185 return $updated_cols;
189 my ($self, $source) = splice @_, 0, 2;
190 my ($fields, $where) = @_;
191 my $wantarray = wantarray;
193 my $blob_cols = $self->_remove_blob_cols($source, $fields);
197 @res = $self->next::method($source, @_);
199 $res[0] = $self->next::method($source, @_);
202 $self->_update_blobs($source, $blob_cols, $where) if %$blob_cols;
204 return $wantarray ? @res : $res[0];
207 sub _remove_blob_cols {
208 my ($self, $source, $fields) = @_;
212 for my $col (keys %$fields) {
213 if ($self->_is_lob_type($source->column_info($col)->{data_type})) {
214 $blob_cols{$col} = delete $fields->{$col};
215 $fields->{$col} = \"''";
223 my ($self, $source, $blob_cols, $where) = @_;
225 my (@primary_cols) = $source->primary_columns;
227 croak "Cannot update TEXT/IMAGE column(s) without a primary key"
228 unless @primary_cols;
230 # check if we're updating a single row by PK
231 my $pk_cols_in_where = 0;
232 for my $col (@primary_cols) {
233 $pk_cols_in_where++ if defined $where->{$col};
237 if ($pk_cols_in_where == @primary_cols) {
239 @row_to_update{@primary_cols} = @{$where}{@primary_cols};
240 @rows = \%row_to_update;
242 my $rs = $source->resultset->search(
245 result_class => 'DBIx::Class::ResultClass::HashRefInflator',
246 select => \@primary_cols
249 @rows = $rs->all; # statement must finish
252 for my $row (@rows) {
253 $self->_insert_blobs($source, $blob_cols, $row);
258 my ($self, $source, $blob_cols, $row) = @_;
259 my $dbh = $self->dbh;
261 my $table = $source->from;
264 my (@primary_cols) = $source->primary_columns;
266 croak "Cannot update TEXT/IMAGE column(s) without a primary key"
267 unless @primary_cols;
269 if ((grep { defined $row{$_} } @primary_cols) != @primary_cols) {
270 if (@primary_cols == 1) {
271 my $col = $primary_cols[0];
272 $row{$col} = $self->last_insert_id($source, $col);
274 croak "Cannot update TEXT/IMAGE column(s) without primary key values";
278 for my $col (keys %$blob_cols) {
279 my $blob = $blob_cols->{$col};
282 if (not $self->isa('DBIx::Class::Storage::DBI::NoBindVars')) {
283 my $search_cond = join ',' => map "$_ = ?", @primary_cols;
286 "select $col from $table where $search_cond"
288 $sth->execute(map $row{$_}, @primary_cols);
290 my $search_cond = join ',' => map "$_ = $row{$_}", @primary_cols;
292 $sth = $dbh->prepare(
293 "select $col from $table where $search_cond"
299 while ($sth->fetch) {
300 $sth->func('CS_GET', 1, 'ct_data_info') or die $sth->errstr;
302 $sth->func('ct_prepare_send') or die $sth->errstr;
304 my $log_on_update = $self->_blob_log_on_update;
305 $log_on_update = 1 if not defined $log_on_update;
307 $sth->func('CS_SET', 1, {
308 total_txtlen => length($blob),
309 log_on_update => $log_on_update
310 }, 'ct_data_info') or die $sth->errstr;
312 $sth->func($blob, length($blob), 'ct_send_data') or die $sth->errstr;
314 $sth->func('ct_finish_send') or die $sth->errstr;
318 croak $exception if $exception;
322 =head2 connect_call_datetime_setup
326 on_connect_call => 'datetime_setup'
328 In L<DBIx::Class::Storage::DBI/connect_info> to set:
330 $dbh->syb_date_fmt('ISO_strict'); # output fmt: 2004-08-21T14:36:48.080Z
331 $dbh->do('set dateformat mdy'); # input fmt: 08/13/1979 18:08:55.080
333 On connection for use with L<DBIx::Class::InflateColumn::DateTime>, using
334 L<DateTime::Format::Sybase>, which you will need to install.
336 This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
337 C<SMALLDATETIME> columns only have minute precision.
342 my $old_dbd_warned = 0;
344 sub connect_call_datetime_setup {
346 my $dbh = $self->_dbh;
348 if ($dbh->can('syb_date_fmt')) {
349 $dbh->syb_date_fmt('ISO_strict');
350 } elsif (not $old_dbd_warned) {
351 carp "Your DBD::Sybase is too old to support ".
352 "DBIx::Class::InflateColumn::DateTime, please upgrade!";
356 $dbh->do('set dateformat mdy');
362 sub datetime_parser_type { "DateTime::Format::Sybase" }
364 sub _dbh_last_insert_id {
365 my ($self, $dbh, $source, $col) = @_;
367 # sorry, there's no other way!
368 my $sth = $self->sth("select max($col) from ".$source->from);
369 my ($id) = $dbh->selectrow_array($sth);
377 =head1 MAXIMUM CONNECTIONS
379 L<DBD::Sybase> makes separate connections to the server for active statements in
380 the background. By default the number of such connections is limited to 25, on
381 both the client side and the server side.
383 This is a bit too low, so on connection the clientside setting is set to C<256>
384 (see L<DBD::Sybase/maxConnect>.) You can override it to whatever setting you
388 L<http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sag1/html/sag1/sag1272.htm>
389 for information on changing the setting on the server side.
393 See L</connect_call_datetime_setup> to setup date formats
394 for L<DBIx::Class::InflateColumn::DateTime>.
396 =head1 IMAGE AND TEXT COLUMNS
398 L<DBD::Sybase> compiled with FreeTDS will B<NOT> work with C<TEXT/IMAGE>
401 See L</connect_call_blob_setup> for a L<DBIx::Class::Storage::DBI/connect_info>
402 setting you need to work with C<IMAGE> columns.
406 See L<DBIx::Class/CONTRIBUTORS>.
410 You may distribute this code under the same terms as Perl itself.