cleanups
[dbsrgits/DBIx-Class.git] / lib / DBIx / Class / Storage / DBI / Sybase.pm
1 package DBIx::Class::Storage::DBI::Sybase;
2
3 use strict;
4 use warnings;
5
6 use Class::C3;
7 use base qw/DBIx::Class::Storage::DBI/;
8
9 use Carp::Clan qw/^DBIx::Class/;
10
11 sub _rebless {
12   my $self = shift;
13
14   if (ref($self) eq 'DBIx::Class::Storage::DBI::Sybase') {
15     my $dbtype = eval {
16       @{$self->dbh->selectrow_arrayref(qq{sp_server_info \@attribute_id=1})}[2]
17     } || '';
18
19     my $exception = $@;
20     $dbtype =~ s/\W/_/gi;
21     my $subclass = "DBIx::Class::Storage::DBI::Sybase::${dbtype}";
22
23     if (!$exception && $dbtype && $self->load_optional_class($subclass)) {
24       bless $self, $subclass;
25       $self->_rebless;
26     } else {
27       # real Sybase
28       if (not $self->dbh->{syb_dynamic_supported}) {
29         bless $self, 'DBIx::Class::Storage:DBI::Sybase::NoBindVars';
30         $self->_rebless;
31       }
32       $self->connect_call_datetime_setup;
33       $self->connect_call_blob_setup;
34     }
35   }
36 }
37
38 sub _populate_dbh {
39   my $self = shift;
40   $self->next::method(@_);
41   $self->connect_call_datetime_setup;
42   $self->connect_call_blob_setup;
43   1;
44 }
45
46 =head2 connect_call_blob_setup
47
48 Used as:
49
50   on_connect_call => 'blob_setup'
51
52 Does C<< $dbh->{syb_binary_images} = 1; >> to return C<IMAGE> data as raw binary
53 instead of as a hex string.
54
55 Recommended.
56
57 =cut
58
59 sub connect_call_blob_setup {
60   my $self = shift;
61   my $dbh = $self->_dbh;
62   $dbh->{syb_binary_images} = 1;
63 }
64
65 {
66   my $old_dbd_warned = 0;
67
68 =head2 connect_call_datetime_setup
69
70 Used as:
71
72   on_connect_call => 'datetime_setup'
73
74 In L<DBIx::Class::Storage::DBI/connect_info> to set:
75
76   $dbh->syb_date_fmt('ISO_strict'); # output fmt: 2004-08-21T14:36:48.080Z
77   $dbh->do('set dateformat mdy');   # input fmt:  08/13/1979 18:08:55.080
78
79 On connection for use with L<DBIx::Class::InflateColumn::DateTime>, using
80 L<DateTime::Format::Sybase>, which you will need to install.
81
82 This works for both C<DATETIME> and C<SMALLDATETIME> columns, although
83 C<SMALLDATETIME> columns only have minute precision.
84
85 =cut
86
87   sub connect_call_datetime_setup {
88     my $self = shift;
89     my $dbh = $self->_dbh;
90
91     if ($dbh->can('syb_date_fmt')) {
92       $dbh->syb_date_fmt('ISO_strict');
93     } elsif (not $old_dbd_warned) {
94       carp "Your DBD::Sybase is too old to support ".
95       "DBIx::Class::InflateColumn::DateTime, please upgrade!";
96       $old_dbd_warned = 1;
97     }
98
99     $dbh->do('set dateformat mdy');
100
101     1;
102   }
103 }
104
105 sub datetime_parser_type { "DateTime::Format::Sybase" }
106
107 sub _dbh_last_insert_id {
108   my ($self, $dbh, $source, $col) = @_;
109
110   # sorry, there's no other way!
111   my $sth = $dbh->prepare_cached("select max($col) from ".$source->from);
112   return ($dbh->selectrow_array($sth))[0];
113 }
114
115 =head2 count
116
117 Counts for limited queries are emulated by executing select queries and
118 returning the number of successful executions minus the offset.
119
120 This is necessary due to the limitations of Sybase.
121
122 =cut
123
124 sub count {
125   my $self = shift;
126   my ($source, $attrs) = @_;
127
128   if (not exists $attrs->{rows}) {
129     return $self->next::method(@_);
130   }
131
132   my $offset = $attrs->{offset} || 0;
133   my $total  = $attrs->{rows} + $offset;
134
135   my $new_attrs = $self->_copy_attributes_for_count($source, $attrs);
136
137   my $first_pk = ($source->primary_columns)[0];
138
139   $new_attrs->{select} = $first_pk ? "me.$first_pk" : 1;
140
141   my $tmp_rs = $source->resultset_class->new($source, $new_attrs);
142
143   $self->dbh->{syb_rowcount} = $total;
144
145   my $count = 0;
146   $count++ while $tmp_rs->cursor->next;
147
148   $self->dbh->{syb_rowcount} = 0;
149
150   return $count - $offset;
151 }
152
153 1;
154
155 =head1 NAME
156
157 DBIx::Class::Storage::DBI::Sybase - Storage::DBI subclass for Sybase
158
159 =head1 SYNOPSIS
160
161 This subclass supports L<DBD::Sybase> for real Sybase databases.  If you are
162 using an MSSQL database via L<DBD::Sybase>, your storage will be reblessed to
163 L<DBIx::Class::Storage::DBI::Sybase::Microsoft_SQL_Server>.
164
165 =head1 DESCRIPTION
166
167 If your version of Sybase does not support placeholders, then your storage
168 will be reblessed to L<DBIx::Class::Storage::DBI::Sybase::NoBindVars>. You can
169 also enable that driver explicitly, see the documentation for more details.
170
171 With this driver there is unfortunately no way to get the C<last_insert_id>
172 without doing a C<select max(col)>.
173
174 But your queries will be cached.
175
176 A recommended L<DBIx::Class::Storage::DBI/connect_info> setting:
177
178   on_connect_call => [qw/datetime_setup blob_setup/]
179
180 =head1 DATES
181
182 See L</connect_call_datetime_setup> to setup date formats
183 for L<DBIx::Class::InflateColumn::DateTime>.
184
185 =head1 IMAGE AND TEXT COLUMNS
186
187 See L</connect_call_blob_setup> for a L<DBIx::Class::Storage::DBI/connect_info>
188 setting you need to work with C<IMAGE> columns.
189
190 Due to limitations in L<DBD::Sybase> and this driver, it is only possible to
191 select one C<TEXT> or C<IMAGE> column at a time, and it must be at the end of
192 your C<select> list (one way to insure that is to define the column last in your
193 C<Result> class.)
194
195 =head1 AUTHORS
196
197 See L<DBIx::Class/CONTRIBUTORS>.
198
199 =head1 LICENSE
200
201 You may distribute this code under the same terms as Perl itself.
202
203 =cut
204 # vim:sts=2 sw=2: