set maxConnect in DSN and add docs
[dbsrgits/DBIx-Class-Historic.git] / lib / DBIx / Class / Storage / DBI / Sybase.pm
CommitLineData
3885cff6 1package DBIx::Class::Storage::DBI::Sybase;
2
3use strict;
4use warnings;
2ad62d97 5
eabab5d0 6use base qw/
64f4e691 7 DBIx::Class::Storage::DBI::Sybase::Base
b0b44f97 8 DBIx::Class::Storage::DBI
eabab5d0 9/;
2ad62d97 10use mro 'c3';
6b1f5ef7 11use Carp::Clan qw/^DBIx::Class/;
12
98259fe4 13=head1 NAME
14
15DBIx::Class::Storage::DBI::Sybase - Storage::DBI subclass for Sybase
16
17=head1 SYNOPSIS
18
19This subclass supports L<DBD::Sybase> for real Sybase databases. If you are
20using an MSSQL database via L<DBD::Sybase>, your storage will be reblessed to
21L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
22
23=head1 DESCRIPTION
24
25If your version of Sybase does not support placeholders, then your storage
26will be reblessed to L<DBIx::Class::Storage::DBI::Sybase::NoBindVars>. You can
27also enable that driver explicitly, see the documentation for more details.
28
29With this driver there is unfortunately no way to get the C<last_insert_id>
30without doing a C<select max(col)>.
31
32But your queries will be cached.
33
fd5a07e4 34A recommended L<DBIx::Class::Storage::DBI/connect_info> settings:
98259fe4 35
fd5a07e4 36 on_connect_call => [['datetime_setup'], [blob_setup => log_on_update => 0]]
98259fe4 37
38=head1 METHODS
39
40=cut
41
fd5a07e4 42__PACKAGE__->mk_group_accessors('simple' =>
43 qw/_blob_log_on_update/
44);
45
47d9646a 46sub _rebless {
b50a5275 47 my $self = shift;
c5ce7cd6 48
49 if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') {
50 my $dbtype = eval {
51 @{$self->dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2]
52 } || '';
53
54 my $exception = $@;
55 $dbtype =~ s/\W/_/gi;
56 my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
57
58 if (!$exception && $dbtype && $self->load_optional_class($subclass)) {
59 bless $self, $subclass;
60 $self->_rebless;
683f73ec 61 } else {
62 # real Sybase
63 if (not $self->dbh->{syb_dynamic_supported}) {
d71d78d8 64 $self->ensure_class_loaded('DBIx::Class::Storage::DBI::Sybase::NoBindVars');
65 bless $self, 'DBIx::Class::Storage::DBI::Sybase::NoBindVars';
683f73ec 66 $self->_rebless;
67 }
41c93b1b 68 $self->_set_maxConnect;
47d9646a 69 }
c5ce7cd6 70 }
b50a5275 71}
72
41c93b1b 73sub _set_maxConnect {
74 my $self = shift;
75
76 my $dsn = $self->_dbi_connect_info->[0];
77
78 return if ref($dsn) eq 'CODE';
79
80 if ($dsn !~ /maxConnect=/) {
81 $self->_dbi_connect_info->[0] = "$dsn;maxConnect=256";
82 # will take effect next connection
83 my $connected = defined $self->_dbh;
84 $self->disconnect;
85 $self->ensure_connected if $connected;
86 }
87}
88
63d46bb3 89=head2 connect_call_blob_setup
90
91Used as:
92
fd5a07e4 93 on_connect_call => [ [ blob_setup => log_on_update => 0 ] ]
63d46bb3 94
95Does C<< $dbh->{syb_binary_images} = 1; >> to return C<IMAGE> data as raw binary
96instead of as a hex string.
97
6636ad53 98Recommended.
99
fd5a07e4 100Also sets the C<log_on_update> value for blob write operations. The default is
101C<1>, but C<0> is better if your database is configured for it.
102
103See
104L<DBD::Sybase/Handling_IMAGE/TEXT_data_with_syb_ct_get_data()/syb_ct_send_data()>.
105
63d46bb3 106=cut
107
108sub connect_call_blob_setup {
109 my $self = shift;
fd5a07e4 110 my %args = @_;
63d46bb3 111 my $dbh = $self->_dbh;
112 $dbh->{syb_binary_images} = 1;
fd5a07e4 113
114 $self->_blob_log_on_update($args{log_on_update})
115 if exists $args{log_on_update};
116}
117
118sub _is_lob_type {
119 my $self = shift;
120 shift =~ /(?:text|image|lob|bytea|binary)/i;
121}
122
123sub insert {
7d17f469 124 my ($self, $source, $to_insert) = splice @_, 0, 3;
125
126 my $blob_cols = $self->_remove_blob_cols($source, $to_insert);
127
128 my $updated_cols = $self->next::method($source, $to_insert, @_);
129
130 $self->_update_blobs($source, $blob_cols, $to_insert) if %$blob_cols;
131
132 return $updated_cols;
133}
134
135#sub update {
136# my ($self, $source) = splice @_, 0, 2;
137# my ($fields) = @_;
138#
139# my $blob_cols = $self->_remove_blob_cols($source, $fields);
140#
141# my @res = 1;
142#
143# if (%$fields) {
144# if (wantarray) {
145# @res = $self->next::method($source, @_);
146# } else {
147# $res[0] = $self->next::method($source, @_);
148# }
149# }
150#
151# $self->_update_blobs($source, $blob_cols, $fields) if %$blob_cols;
152#
153# return wantarray ? @res : $res[0];
154#}
155
156sub _remove_blob_cols {
157 my ($self, $source, $fields) = @_;
fd5a07e4 158
159 my %blob_cols;
160
7d17f469 161 for my $col (keys %$fields) {
162 $blob_cols{$col} = delete $fields->{$col}
fd5a07e4 163 if $self->_is_lob_type($source->column_info($col)->{data_type});
164 }
165
7d17f469 166 return \%blob_cols;
fd5a07e4 167}
168
169sub _update_blobs {
170 my ($self, $source, $blob_cols, $inserted) = @_;
171 my $dbh = $self->dbh;
172
173 my $table = $source->from;
174
175 my (@primary_cols) = $source->primary_columns;
176
177 croak "Cannot update TEXT/IMAGE without a primary key!"
178 unless @primary_cols;
179
180 my $search_cond = join ',' => map "$_ = ?", @primary_cols;
181
182 for my $col (keys %$blob_cols) {
183 my $blob = $blob_cols->{$col};
184
185# First update to empty string in case it's NULL, can't update a NULL blob using
186# the API.
187 my $sth = $dbh->prepare_cached(
188 qq{update $table set $col = '' where $search_cond}
189 );
190 $sth->execute(map $inserted->{$_}, @primary_cols) or die $sth->errstr;
191 $sth->finish;
192
193 $sth = $dbh->prepare_cached(
194 "select $col from $table where $search_cond"
195 );
196 $sth->execute(map $inserted->{$_}, @primary_cols);
197
198 eval {
199 while ($sth->fetch) {
200 $sth->func('CS_GET', 1, 'ct_data_info') or die $sth->errstr;
201 }
202 $sth->func('ct_prepare_send') or die $sth->errstr;
203
204 my $log_on_update = $self->_blob_log_on_update;
205 $log_on_update = 1 if not defined $log_on_update;
206
207 $sth->func('CS_SET', 1, {
208 total_txtlen => length($blob),
209 log_on_update => $log_on_update
210 }, 'ct_data_info') or die $sth->errstr;
211
212 $sth->func($blob, length($blob), 'ct_send_data') or die $sth->errstr;
213
214 $sth->func('ct_finish_send') or die $sth->errstr;
215 };
216 my $exception = $@;
217 $sth->finish;
218 croak $exception if $exception;
219 }
63d46bb3 220}
221
9539eeb1 222=head2 connect_call_datetime_setup
223
224Used as:
225
226 on_connect_call => 'datetime_setup'
227
228In L<DBIx::Class::Storage::DBI/connect_info> to set:
229
3abafb11 230 $dbh->syb_date_fmt('ISO_strict'); # output fmt: 2004-08-21T14:36:48.080Z
231 $dbh->do('set dateformat mdy'); # input fmt: 08/13/1979 18:08:55.080
9539eeb1 232
233On connection for use with L<DBIx::Class::InflateColumn::DateTime>, using
3abafb11 234L<DateTime::Format::Sybase>, which you will need to install.
235
236This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
237C<SMALLDATETIME> columns only have minute precision.
9539eeb1 238
239=cut
240
9041a97a 241{
242 my $old_dbd_warned = 0;
243
9539eeb1 244 sub connect_call_datetime_setup {
6b1f5ef7 245 my $self = shift;
6b1f5ef7 246 my $dbh = $self->_dbh;
247
248 if ($dbh->can('syb_date_fmt')) {
249 $dbh->syb_date_fmt('ISO_strict');
250 } elsif (not $old_dbd_warned) {
251 carp "Your DBD::Sybase is too old to support ".
252 "DBIx::Class::InflateColumn::DateTime, please upgrade!";
253 $old_dbd_warned = 1;
254 }
255
256 $dbh->do('set dateformat mdy');
c5ce7cd6 257
6b1f5ef7 258 1;
c5ce7cd6 259 }
6b1f5ef7 260}
261
6636ad53 262sub datetime_parser_type { "DateTime::Format::Sybase" }
263
6b1f5ef7 264sub _dbh_last_insert_id {
265 my ($self, $dbh, $source, $col) = @_;
c5ce7cd6 266
267 # sorry, there's no other way!
268 my $sth = $dbh->prepare_cached("select max($col) from ".$source->from);
269 return ($dbh->selectrow_array($sth))[0];
a964a928 270}
271
3885cff6 2721;
273
41c93b1b 274=head1 MAXIMUM CONNECTIONS
275
276L<DBD::Sybase> makes separate connections to the server for active statements in
277the background. By default the number of such connections is limited to 25, on
278both the client side and the server side.
279
280This is a bit too low, so on connection the clientside setting is set to C<256>
281(see L<DBD::Sybase/maxConnect>.) You can override it to whatever setting you
282like in the DSN.
283
284See
285L<http://infocenter.sybase.com/help/index.jsp?topic=/com.sybase.help.ase_15.0.sag1/html/sag1/sag1272.htm>
286for information on changing the setting on the server side.
287
c5ce7cd6 288=head1 DATES
289
3abafb11 290See L</connect_call_datetime_setup> to setup date formats
291for L<DBIx::Class::InflateColumn::DateTime>.
c5ce7cd6 292
6636ad53 293=head1 IMAGE AND TEXT COLUMNS
63d46bb3 294
295See L</connect_call_blob_setup> for a L<DBIx::Class::Storage::DBI/connect_info>
296setting you need to work with C<IMAGE> columns.
297
6636ad53 298Due to limitations in L<DBD::Sybase> and this driver, it is only possible to
9041a97a 299select one C<TEXT> or C<IMAGE> column at a time.
6636ad53 300
3885cff6 301=head1 AUTHORS
302
7e8cecc1 303See L<DBIx::Class/CONTRIBUTORS>.
c5ce7cd6 304
3885cff6 305=head1 LICENSE
306
307You may distribute this code under the same terms as Perl itself.
308
309=cut
c5ce7cd6 310# vim:sts=2 sw=2: