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 - Storage::DBI subclass for Sybase
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 at least version C<1.09> of L<DBD::Sybase> for placeholder support.
35 Otherwise your storage will be automatically reblessed into C<::NoBindVars>.
37 A recommended L<DBIx::Class::Storage::DBI/connect_info> settings:
39 on_connect_call => [['datetime_setup'], [blob_setup => log_on_update => 0]]
45 __PACKAGE__->mk_group_accessors('simple' =>
46 qw/_blob_log_on_update/
52 if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') {
54 @{$self->dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2]
59 my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
61 if (!$exception && $dbtype && $self->load_optional_class($subclass)) {
62 bless $self, $subclass;
64 } else { # real Sybase
65 my $no_bind_vars = 'DBIx::Class::Storage::DBI::Sybase::NoBindVars';
67 if (not $self->dbh->{syb_dynamic_supported}) {
68 $self->ensure_class_loaded($no_bind_vars);
69 bless $self, $no_bind_vars;
73 if ($DBD::Sybase::VERSION < 1.09) {
76 Your version of Sybase potentially supports placeholders and query caching,
77 however your version of DBD::Sybase is too old to do this properly. Please
78 upgrade to at least version 1.09 if you want this feature.
80 TEXT/IMAGE column support will also not work in older versions of DBD::Sybase.
82 See perldoc DBIx::Class::Storage::DBI::Sybase for more details.
84 $self->ensure_class_loaded($no_bind_vars);
85 bless $self, $no_bind_vars;
88 $self->_set_maxConnect;
96 my $dsn = $self->_dbi_connect_info->[0];
98 return if ref($dsn) eq 'CODE';
100 if ($dsn !~ /maxConnect=/) {
101 $self->_dbi_connect_info->[0] = "$dsn;maxConnect=256";
102 my $connected = defined $self->_dbh;
104 $self->ensure_connected if $connected;
108 =head2 connect_call_blob_setup
112 on_connect_call => [ [ blob_setup => log_on_update => 0 ] ]
114 Does C<< $dbh->{syb_binary_images} = 1; >> to return C<IMAGE> data as raw binary
115 instead of as a hex string.
119 Also sets the C<log_on_update> value for blob write operations. The default is
120 C<1>, but C<0> is better if your database is configured for it.
123 L<DBD::Sybase/Handling_IMAGE/TEXT_data_with_syb_ct_get_data()/syb_ct_send_data()>.
127 sub connect_call_blob_setup {
130 my $dbh = $self->_dbh;
131 $dbh->{syb_binary_images} = 1;
133 $self->_blob_log_on_update($args{log_on_update})
134 if exists $args{log_on_update};
140 $type && $type =~ /(?:text|image|lob|bytea|binary)/i;
143 # Move TEXT/IMAGE column to the end of select list, and make sure there is only
148 # * column indexes need to be fixed if @$select is reordered, not sure if that's
150 # * needs to handle hashrefs
151 # * for some reason tests pass without this, even though documentation says
152 # blobs should be at the end of the select list
153 # * needs to at least croak for multiple blobs
156 # my ($self, $ident, $select) = splice @_, 0, 3;
158 # my ($alias2src, $rs_alias) = $self->_resolve_ident_sources($ident);
159 # my $name_sep = $self->_sql_maker_opts->{name_sep} || '.';
161 # my (@non_blobs, @blobs);
163 # for my $col (@$select) {
165 ## XXX should handle hashrefs too
166 # push @non_blobs, $col;
170 # $col =~ s/^([^\Q${name_sep}\E]*)\Q${name_sep}\E//;
171 # my $alias = $1 || $rs_alias;
172 # my $rsrc = $alias2src->{$alias};
173 # my $datatype = $rsrc && $rsrc->column_info($col)->{data_type};
175 # if ($self->_is_lob_type($datatype)) {
178 # push @non_blobs, $col;
182 # croak "cannot select more than a one TEXT/IMAGE column"
185 # $self->next::method($ident, [@non_blobs, @blobs], @_);
188 # override to handle TEXT/IMAGE
190 my ($self, $source, $to_insert) = splice @_, 0, 3;
192 my $blob_cols = $self->_remove_blob_cols($source, $to_insert);
194 my $updated_cols = $self->next::method($source, $to_insert, @_);
196 $self->_update_blobs($source, $blob_cols, $to_insert) if %$blob_cols;
198 return $updated_cols;
202 # my ($self, $source) = splice @_, 0, 2;
205 # my $blob_cols = $self->_remove_blob_cols($source, $fields);
211 # @res = $self->next::method($source, @_);
213 # $res[0] = $self->next::method($source, @_);
217 # $self->_update_blobs($source, $blob_cols, $fields) if %$blob_cols;
219 # return wantarray ? @res : $res[0];
222 sub _remove_blob_cols {
223 my ($self, $source, $fields) = @_;
227 for my $col (keys %$fields) {
228 if ($self->_is_lob_type($source->column_info($col)->{data_type})) {
229 $blob_cols{$col} = delete $fields->{$col};
230 $fields->{$col} = \"''";
238 my ($self, $source, $blob_cols, $inserted) = @_;
239 my $dbh = $self->dbh;
241 my $table = $source->from;
243 my %inserted = %$inserted;
244 my (@primary_cols) = $source->primary_columns;
246 croak "Cannot update TEXT/IMAGE column(s) without a primary key"
247 unless @primary_cols;
249 if ((grep { defined $inserted{$_} } @primary_cols) != @primary_cols) {
250 if (@primary_cols == 1) {
251 my $col = $primary_cols[0];
252 $inserted{$col} = $self->last_insert_id($source, $col);
254 croak "Cannot update TEXT/IMAGE column(s) without primary key values";
258 for my $col (keys %$blob_cols) {
259 my $blob = $blob_cols->{$col};
262 if (not $self->isa('DBIx::Class::Storage::DBI::NoBindVars')) {
263 my $search_cond = join ',' => map "$_ = ?", @primary_cols;
266 "select $col from $table where $search_cond"
268 $sth->execute(map $inserted{$_}, @primary_cols);
270 my $search_cond = join ',' => map "$_ = $inserted{$_}", @primary_cols;
272 $sth = $dbh->prepare(
273 "select $col from $table where $search_cond"
279 while ($sth->fetch) {
280 $sth->func('CS_GET', 1, 'ct_data_info') or die $sth->errstr;
282 $sth->func('ct_prepare_send') or die $sth->errstr;
284 my $log_on_update = $self->_blob_log_on_update;
285 $log_on_update = 1 if not defined $log_on_update;
287 $sth->func('CS_SET', 1, {
288 total_txtlen => length($blob),
289 log_on_update => $log_on_update
290 }, 'ct_data_info') or die $sth->errstr;
292 $sth->func($blob, length($blob), 'ct_send_data') or die $sth->errstr;
294 $sth->func('ct_finish_send') or die $sth->errstr;
298 croak $exception if $exception;
302 =head2 connect_call_datetime_setup
306 on_connect_call => 'datetime_setup'
308 In L<DBIx::Class::Storage::DBI/connect_info> to set:
310 $dbh->syb_date_fmt('ISO_strict'); # output fmt: 2004-08-21T14:36:48.080Z
311 $dbh->do('set dateformat mdy'); # input fmt: 08/13/1979 18:08:55.080
313 On connection for use with L<DBIx::Class::InflateColumn::DateTime>, using
314 L<DateTime::Format::Sybase>, which you will need to install.
316 This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
317 C<SMALLDATETIME> columns only have minute precision.
322 my $old_dbd_warned = 0;
324 sub connect_call_datetime_setup {
326 my $dbh = $self->_dbh;
328 if ($dbh->can('syb_date_fmt')) {
329 $dbh->syb_date_fmt('ISO_strict');
330 } elsif (not $old_dbd_warned) {
331 carp "Your DBD::Sybase is too old to support ".
332 "DBIx::Class::InflateColumn::DateTime, please upgrade!";
336 $dbh->do('set dateformat mdy');
342 sub datetime_parser_type { "DateTime::Format::Sybase" }
344 sub _dbh_last_insert_id {
345 my ($self, $dbh, $source, $col) = @_;
347 # sorry, there's no other way!
348 my $sth = $dbh->prepare_cached("select max($col) from ".$source->from);
349 return ($dbh->selectrow_array($sth))[0];
354 =head1 MAXIMUM CONNECTIONS
356 L<DBD::Sybase> makes separate connections to the server for active statements in
357 the background. By default the number of such connections is limited to 25, on
358 both the client side and the server side.
360 This is a bit too low, so on connection the clientside setting is set to C<256>
361 (see L<DBD::Sybase/maxConnect>.) You can override it to whatever setting you
365 L<http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sag1/html/sag1/sag1272.htm>
366 for information on changing the setting on the server side.
370 See L</connect_call_datetime_setup> to setup date formats
371 for L<DBIx::Class::InflateColumn::DateTime>.
373 =head1 IMAGE AND TEXT COLUMNS
375 You need at least version C<1.09> of L<DBD::Sybase> for C<TEXT/IMAGE> column
378 See L</connect_call_blob_setup> for a L<DBIx::Class::Storage::DBI/connect_info>
379 setting you need to work with C<IMAGE> columns.
381 Due to limitations in L<DBD::Sybase> and this driver, it is only possible to
382 select one C<TEXT> or C<IMAGE> column at a time. This is handled automatically
383 for tables with only one such column, if you have more than one, supply a
384 C<< select => [qw/col list .../] >> key to your C<< ->search >> calls, with the
385 single desired C<TEXT/IMAGE> column at the end of the list.
389 See L<DBIx::Class/CONTRIBUTORS>.
393 You may distribute this code under the same terms as Perl itself.